Index: .fossil-settings/ignore-glob ================================================================== --- .fossil-settings/ignore-glob +++ .fossil-settings/ignore-glob @@ -22,11 +22,11 @@ */wish* */tktest* */versions.vc */version.vc */libtk.vfs -*/libtk_*.zip +*/libtk*.zip html macosx/configure win/Debug* win/Release* win/*.manifest ADDED .github/ISSUE_TEMPLATE.md Index: .github/ISSUE_TEMPLATE.md ================================================================== --- /dev/null +++ .github/ISSUE_TEMPLATE.md @@ -0,0 +1,3 @@ +Important Note +========== +Please 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. ADDED .github/PULL_REQUEST_TEMPLATE.md Index: .github/PULL_REQUEST_TEMPLATE.md ================================================================== --- /dev/null +++ .github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,3 @@ +Important Note +========== +Please 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. ADDED .github/workflows/linux-build.yml Index: .github/workflows/linux-build.yml ================================================================== --- /dev/null +++ .github/workflows/linux-build.yml @@ -0,0 +1,154 @@ +name: Linux +on: [push] +defaults: + run: + shell: bash + working-directory: tk/unix +env: + ERROR_ON_FAILURES: 1 +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + - "clang" + cfgopt: + - "" + - "CFLAGS=-DTK_NO_DEPRECATED=1" + - "--disable-shared" + - "--disable-xft" + - "--disable-xss" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-6-branch + path: tcl + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install tcl8.6-dev libxss-dev + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT --with-tcl=/usr/lib/tcl8.6" --disable-zipfs >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + echo "TOOL_DIR=$(cd tcl/tools;pwd)" >> $GITHUB_ENV + echo "BUILD_CONFIG_ID=$OPTS" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + OPTS: ${{ matrix.compiler }}${{ matrix.cfgopt }} + - name: Configure (opts=${{ matrix.cfgopt }}) + run: | + ./configure $CFGOPT "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries || { + echo "::error::Failure during Build" + exit 1 + } + - name: Build Test Harness + run: | + make tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Test-Drive Installation + run: | + make install || { + echo "::error::Failure during Install" + exit 1 + } + - name: Create Distribution Package + run: | + make dist || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Convert Documentation to HTML + run: | + make html-tk TOOL_DIR=$TOOL_DIR || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Discover Version ID + if: ${{ env.BUILD_CONFIG_ID == 'gcc' }} + run: | + cd /tmp/dist + echo "VERSION=`ls -d tk* | sed 's/tk//'`" >> $GITHUB_ENV + - name: Upload Source Distribution + if: ${{ env.BUILD_CONFIG_ID == 'gcc-no' }} + uses: actions/upload-artifact@v2 + with: + name: Tk ${{ env.VERSION }} Source distribution (snapshot) + path: | + /tmp/dist/tk* + !/tmp/dist/tk*/html/** + - name: Upload Documentation Distribution + if: ${{ env.BUILD_CONFIG_ID == 'gcc-no' }} + uses: actions/upload-artifact@v2 + with: + name: Tk ${{ env.VERSION }} HTML documentation (snapshot) + path: /tmp/dist/tk*/html + test: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + cfgopt: + - "" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install tcl8.6-dev libxss-dev xvfb + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT --with-tcl=/usr/lib/tcl8.6 --disable-zipfs" >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + - name: Configure ${{ matrix.cfgopt }} + run: | + ./configure $CFGOPT "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + xvfb-run --auto-servernum make test-classic | tee out-classic.txt + xvfb-run --auto-servernum make test-ttk | tee out-ttk.txt + grep -q "Failed 0" out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } ADDED .github/workflows/linux-with-tcl8-build.yml Index: .github/workflows/linux-with-tcl8-build.yml ================================================================== --- /dev/null +++ .github/workflows/linux-with-tcl8-build.yml @@ -0,0 +1,186 @@ +name: Linux (with Tcl 8.7) +on: [push] +defaults: + run: + shell: bash + working-directory: tk/unix +env: + ERROR_ON_FAILURES: 1 +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + - "clang" + cfgopt: + - "" + - "CFLAGS=-DTK_NO_DEPRECATED=1" + - "--disable-shared" + - "--disable-xft" + - "--disable-xss" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-branch + path: tcl + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install libxss-dev + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT" >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + echo "TOOL_DIR=$(cd tcl/tools;pwd)" >> $GITHUB_ENV + echo "BUILD_CONFIG_ID=$OPTS" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + OPTS: ${{ matrix.compiler }}${{ matrix.cfgopt }} + - name: Configure and Build Tcl + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::warning::Failure during Tcl Configure" + exit 1 + } + make all install || { + echo "::warning::Failure during Tcl Build" + exit 1 + } + echo "TCL_CONFIG_PATH=`pwd`" >> $GITHUB_ENV + working-directory: tcl/unix + - name: Configure (opts=${{ matrix.cfgopt }}) + run: | + ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries || { + echo "::error::Failure during Build" + exit 1 + } + - name: Build Test Harness + run: | + make tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Test-Drive Installation + run: | + make install || { + echo "::error::Failure during Install" + exit 1 + } + - name: Create Distribution Package + run: | + make dist || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Convert Documentation to HTML + run: | + make html-tk TOOL_DIR=$TOOL_DIR || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Discover Version ID + if: ${{ env.BUILD_CONFIG_ID == 'gcc' }} + run: | + cd /tmp/dist + echo "VERSION=`ls -d tk* | sed 's/tk//'`" >> $GITHUB_ENV + - name: Upload Source Distribution + if: ${{ env.BUILD_CONFIG_ID == 'gcc' }} + uses: actions/upload-artifact@v2 + with: + name: Tk ${{ env.VERSION }} Source distribution (snapshot) + path: | + /tmp/dist/tk* + !/tmp/dist/tk*/html/** + - name: Upload Documentation Distribution + if: ${{ env.BUILD_CONFIG_ID == 'gcc' }} + uses: actions/upload-artifact@v2 + with: + name: Tk ${{ env.VERSION }} HTML documentation (snapshot) + path: /tmp/dist/tk*/html + test: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + cfgopt: + - "" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-branch + path: tcl + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install libxss-dev xvfb + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT" >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + - name: Configure and Build Tcl + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::warning::Failure during Tcl Configure" + exit 1 + } + make all install || { + echo "::warning::Failure during Tcl Build" + exit 1 + } + echo "TCL_CONFIG_PATH=`pwd`" >> $GITHUB_ENV + working-directory: tcl/unix + - name: Configure ${{ matrix.cfgopt }} + run: | + ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + xvfb-run --auto-servernum make test-classic | tee out-classic.txt + xvfb-run --auto-servernum make test-ttk | tee out-ttk.txt + grep -q "Failed 0" out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } ADDED .github/workflows/linux-with-tcl9-build.yml Index: .github/workflows/linux-with-tcl9-build.yml ================================================================== --- /dev/null +++ .github/workflows/linux-with-tcl9-build.yml @@ -0,0 +1,172 @@ +name: Linux (with Tcl 9.0) +on: [push] +defaults: + run: + shell: bash + working-directory: tk/unix +env: + ERROR_ON_FAILURES: 1 +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + - "clang" + cfgopt: + - "" + - "CFLAGS=-DTK_NO_DEPRECATED=1" + - "--disable-shared" + - "--disable-xft" + - "--disable-xss" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: main + path: tcl + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install libxss-dev + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT" >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + echo "TOOL_DIR=$(cd tcl/tools;pwd)" >> $GITHUB_ENV + echo "BUILD_CONFIG_ID=$OPTS" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + OPTS: ${{ matrix.compiler }}${{ matrix.cfgopt }} + - name: Configure and Build Tcl + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::warning::Failure during Tcl Configure" + exit 1 + } + make all install || { + echo "::warning::Failure during Tcl Build" + exit 1 + } + echo "TCL_CONFIG_PATH=`pwd`" >> $GITHUB_ENV + working-directory: tcl/unix + - name: Configure (opts=${{ matrix.cfgopt }}) + run: | + ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries || { + echo "::error::Failure during Build" + exit 1 + } + - name: Build Test Harness + run: | + make tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Test-Drive Installation + run: | + make install || { + echo "::error::Failure during Install" + exit 1 + } + - name: Create Distribution Package + run: | + make dist || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Convert Documentation to HTML + run: | + make html-tk TOOL_DIR=$TOOL_DIR || { + echo "::error::Failure during Distribute" + exit 1 + } + - name: Discover Version ID + if: ${{ env.BUILD_CONFIG_ID == 'gcc' }} + run: | + cd /tmp/dist + echo "VERSION=`ls -d tk* | sed 's/tk//'`" >> $GITHUB_ENV + test: + runs-on: ubuntu-20.04 + strategy: + matrix: + compiler: + - "gcc" + cfgopt: + - "" + - "--enable-symbols" + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: main + path: tcl + - name: Setup Environment (compiler=${{ matrix.compiler }}) + run: | + sudo apt-get install libxss-dev xvfb + mkdir "$HOME/install dir" + touch tk/doc/man.macros tk/generic/tkStubInit.c + echo "CFGOPT=$CFGOPT" >> $GITHUB_ENV + echo "CC=$COMPILER" >> $GITHUB_ENV + working-directory: "." + env: + CFGOPT: ${{ matrix.cfgopt }} + COMPILER: ${{ matrix.compiler }} + - name: Configure and Build Tcl + run: | + ./configure ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::warning::Failure during Tcl Configure" + exit 1 + } + make all install || { + echo "::warning::Failure during Tcl Build" + exit 1 + } + echo "TCL_CONFIG_PATH=`pwd`" >> $GITHUB_ENV + working-directory: tcl/unix + - name: Configure ${{ matrix.cfgopt }} + run: | + ./configure $CFGOPT --with-tcl=$TCL_CONFIG_PATH "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + - name: Build + run: | + make binaries libraries tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + xvfb-run --auto-servernum make test-classic | tee out-classic.txt + xvfb-run --auto-servernum make test-ttk | tee out-ttk.txt + grep -q "Failed 0" out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } ADDED .github/workflows/mac-build.yml Index: .github/workflows/mac-build.yml ================================================================== --- /dev/null +++ .github/workflows/mac-build.yml @@ -0,0 +1,162 @@ +name: macOS +on: [push] +env: + ERROR_ON_FAILURES: 1 +jobs: + xcode: + runs-on: macos-11 + defaults: + run: + shell: bash + working-directory: tk/macosx + steps: + - name: Check out Tk + uses: actions/checkout@v2 + with: + path: tk + - name: Check out Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-6-branch + path: tcl + - name: Prepare checked out repositories + run: | + touch tk/generic/tkStubInit.c + mkdir build + echo "BUILD_DIR=`cd build && pwd`" >> $GITHUB_ENV + echo "DESTDIR=`cd build && pwd`" >> $GITHUB_ENV + working-directory: . + - name: Build Tcl + run: | + make all + working-directory: tcl/macosx + - name: Build + run: | + make all install || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + make test | tee out.txt + nmatches=$( grep -c "Failed 0" out.txt ) + if [ $nmatches -lt 4 ] + then + echo "::error::Failure during Test" + exit 1 + fi + clang: + runs-on: macos-11 + strategy: + matrix: + symbols: + - 'no' + - 'mem' + options: + - '--enable-aqua' + - '--disable-aqua' + defaults: + run: + shell: bash + working-directory: tk/unix + steps: + - name: Check out Tk + uses: actions/checkout@v2 + with: + path: tk + - name: Check out Tcl + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-6-branch + path: tcl + - name: Prepare checked out repositories + env: + SET_DISPLAY: ${{ contains(matrix.options, '--disable-aqua') }} + run: | + touch tkStubInit.c + mkdir "$HOME/install dir" + echo "USE_XVFB=$SET_DISPLAY" >> $GITHUB_ENV + working-directory: tk/generic + - name: Add X11 (if required) + if: ${{ env.USE_XVFB == 'true' }} + run: | + brew install --cask xquartz + sudo /opt/X11/libexec/privileged_startx || true + working-directory: . + - name: Build Tcl + # Note that macOS is always a 64 bit platform + run: | + ./configure --enable-64bit ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Tcl Configure" + exit 1 + } + make all || { + echo "::error::Failure during Tcl Build" + exit 1 + } + make install || { + echo "::error::Failure during Tcl Install" + exit 1 + } + working-directory: tcl/unix + env: + CFGOPT: --enable-symbols=${{ matrix.symbols }} + - name: Configure (symbols=${{ matrix.symbols }} ${{matrix.options }}) + # Note that macOS is always a 64 bit platform + run: | + ./configure --enable-64bit ${CFGOPT} "--prefix=$HOME/install dir" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + env: + CFGOPT: --enable-symbols=${{ matrix.symbols }} ${{matrix.options }} + - name: Build + run: | + make all tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + if [ $USE_XVFB == true ]; then + function runXvfb { + PATH=$PATH:/opt/X11/bin + Xvfb $1 & + XVFB_PID=$! + echo Launched Xvfb $1 as process $XVFB_PID >&2 + trap "echo killing process $XVFB_PID... >&2; kill $XVFB_PID" 0 + export DISPLAY=$1 + sleep 2 + } + else + function runXvfb { + echo Xvfb not used, this is a --enable-aqua build + } + fi + ( runXvfb :0; make test-classic; exit $? ) | tee out-classic.txt || { + echo "::error::Failure during Test (classic)" + exit 1 + } + ( runXvfb :0; make test-ttk; exit $? ) | tee out-ttk.txt || { + echo "::error::Failure during Test (ttk)" + exit 1 + } + cat out-classic.txt | grep -q "Failed 0" || { + echo "::error::Failure in classic test results" + exit 1 + } + cat out-ttk.txt | grep -q "Failed 0" || { + echo "::error::Failure in ttk test results" + exit 1 + } + - name: Carry out trial installation + run: | + make install || { + cat config.log + echo "::error::Failure during Install" + exit 1 + } ADDED .github/workflows/onefiledist.yml Index: .github/workflows/onefiledist.yml ================================================================== --- /dev/null +++ .github/workflows/onefiledist.yml @@ -0,0 +1,213 @@ +name: Build Binaries +on: [push] +jobs: + linux: + name: Linux + runs-on: ubuntu-18.04 + defaults: + run: + shell: bash + env: + CC: gcc + CFGOPT: --disable-symbols --disable-shared + steps: + - name: Checkout Tk + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl 8.7 + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-branch + path: tcl + - name: Setup Environment + run: | + sudo apt-get install libxss-dev + touch tcl/generic/tclStubInit.c tcl/generic/tclOOStubInit.c + touch tk/generic/tkStubInit.c + echo "INST_DIR=$(cd install;pwd)" >> $GITHUB_ENV + echo "VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV + working-directory: "." + - name: Configure Tcl + run: | + ./configure $CFGOPT --enable-zipfs --prefix=$INST_DIR + working-directory: tcl/unix + - name: Build & Install Tcl + run: | + make binaries libraries install + make shell SCRIPT="$VER_PATH $GITHUB_ENV" + working-directory: tcl/unix + - name: Configure Tk + run: | + ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR + working-directory: tk/unix + - name: Build & Install Tk + run: | + make binaries libraries install + working-directory: tk/unix + # TODO: need the Tk version separately for distro naming below + - name: Package + run: | + cp bin/wish8.7 ${BUILD_NAME} + chmod +x ${BUILD_NAME} + tar -cf ${BUILD_NAME}.tar ${BUILD_NAME} + working-directory: ${{ env.INST_DIR }} + env: + BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_snapshot + - name: Upload + uses: actions/upload-artifact@v2 + with: + name: Wish ${{ env.TCL_PATCHLEVEL }} Linux single-file build (snapshot) + path: ${{ env.INST_DIR }}/*.tar + - name: Describe Installation Zip Contents + if: ${{ always() }} + run: | + unzip -l wish${{ env.TCL_PATCHLEVEL }}_snapshot || true + working-directory: ${{ env.INST_DIR }} + macos: + name: macOS + runs-on: macos-11 + defaults: + run: + shell: bash + env: + CC: gcc + CFGOPT: --disable-symbols --disable-shared --enable-64bit + steps: + - name: Checkout Tk + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout Tcl 8.7 + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-branch + path: tcl + - name: Checkout create-dmg + uses: actions/checkout@v2 + with: + repository: create-dmg/create-dmg + ref: v1.0.8 + path: create-dmg + - name: Setup Environment + run: | + mkdir -p install/contents + touch tcl/generic/tclStubInit.c tcl/generic/tclOOStubInit.c + touch tk/generic/tkStubInit.c + echo "INST_DIR=$(cd install;pwd)" >> $GITHUB_ENV + echo "VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV + echo "CREATE_DMG=$(cd create-dmg;pwd)/create-dmg" >> $GITHUB_ENV + echo "CFLAGS=-arch x86_64 -arch arm64e" >> $GITHUB_ENV + working-directory: "." + - name: Configure Tcl + run: | + ./configure $CFGOPT --enable-zipfs --prefix=$INST_DIR + working-directory: tcl/unix + - name: Build & Install Tcl + run: | + make binaries libraries install + make shell SCRIPT="$VER_PATH $GITHUB_ENV" + working-directory: tcl/unix + - name: Configure Tk + run: | + ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR \ + --enable-aqua + working-directory: tk/unix + - name: Build & Install Tk + run: | + make binaries libraries install + working-directory: tk/unix + # TODO: need the Tk version separately for distro naming below + - name: Package + run: | + cp ../tk/unix/wish contents/${BUILD_NAME} + chmod +x contents/${BUILD_NAME} + cat > contents/README.txt <> $GITHUB_ENV + echo "VER_PATH=$(cd tcl/tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV + working-directory: "." + - name: Configure Tcl + run: | + ./configure $CFGOPT --enable-zipfs --prefix=$INST_DIR + working-directory: tcl/win + - name: Build & Install Tcl + run: | + make binaries libraries install + $INST_DIR/bin/tclsh* $VER_PATH $GITHUB_ENV + working-directory: tcl/win + - name: Configure Tk + run: | + ./configure $CFGOPT --with-tcl=$INST_DIR/lib --prefix=$INST_DIR + working-directory: tk/win + - name: Build & Install Tk + run: | + make all install + echo "TK_BIN=`pwd`/`echo wish*.exe`" >> $GITHUB_ENV + working-directory: tk/win + # TODO: need the Tk version separately for distro naming below + - name: Package + run: | + cp ${TK_BIN} combined/${BUILD_NAME}.exe + working-directory: install + env: + BUILD_NAME: wish${{ env.TCL_PATCHLEVEL }}_snapshot + - name: Upload + uses: actions/upload-artifact@v2 + with: + name: Wish ${{ env.TCL_PATCHLEVEL }} Windows single-file build (snapshot) + path: install/combined/wish${{ env.TCL_PATCHLEVEL }}_snapshot.exe ADDED .github/workflows/win-build.yml Index: .github/workflows/win-build.yml ================================================================== --- /dev/null +++ .github/workflows/win-build.yml @@ -0,0 +1,160 @@ +name: Windows +on: [push] +env: + ERROR_ON_FAILURES: 1 +jobs: + msvc: + runs-on: windows-2019 + defaults: + run: + shell: powershell + working-directory: tk/win + # Using powershell means we need to explicitly stop on failure + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: tk + - name: Checkout + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-branch + path: tcl + - name: Init MSVC + uses: ilammy/msvc-dev-cmd@v1 + - name: Make Install Location + working-directory: tcl + run: | + echo "TCLDIR=`pwd`" >> $GITHUB_ENV + cd .. + mkdir install + cd install + echo "INSTALLDIR=`pwd`" >> $GITHUB_ENV + - name: Build Tcl + run: | + &nmake -f makefile.vc release install + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + working-directory: tcl/win + - name: Build + run: | + &nmake -f makefile.vc all + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + - name: Build Test Harness + run: | + &nmake -f makefile.vc tktest + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + - name: Run Tests + run: | + nmake -f makefile.vc test-classic | tee out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + nmake -f makefile.vc test-ttk | tee out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } + env: + CI_BUILD_WITH_MSVC: 1 + shell: bash + - name: Build Help + run: | + &nmake -f makefile.vc htmlhelp + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + - name: Install + run: | + &nmake -f makefile.vc install + if ($lastexitcode -ne 0) { + throw "nmake exit code: $lastexitcode" + } + gcc: + runs-on: windows-2019 + defaults: + run: + shell: msys2 {0} + working-directory: win + strategy: + matrix: + symbols: + - "no" + - "mem" + - "all" + steps: + - name: Install MSYS2 + uses: msys2/setup-msys2@v2 + with: + msystem: MINGW64 + install: git mingw-w64-x86_64-toolchain make zip + - name: Checkout + uses: actions/checkout@v2 + - name: Checkout + uses: actions/checkout@v2 + with: + repository: tcltk/tcl + ref: core-8-6-branch + path: tcl + - name: Prepare + run: | + touch tkStubInit.c + touch "${HOME}/forWinDialog-5.12.7" + mkdir "${HOME}/install_dir" + echo "INSTALL_DIR=${HOME}/install_dir" >> $GITHUB_ENV + working-directory: generic + - name: Configure and Build Tcl + run: | + ./configure ${CFGOPT} "--prefix=$INSTALL_DIR" || { + cat config.log + echo "::warning::Failure during Tcl Configure" + exit 1 + } + make all install || { + echo "::warning::Failure during Tcl Build" + exit 1 + } + echo "TCL_CONFIG_PATH=`pwd`" >> $GITHUB_ENV + env: + CFGOPT: --enable-64bit --enable-symbols=${{ matrix.symbols }} + working-directory: tcl/win + - name: Configure (symbols=${{ matrix.symbols }}) + run: | + ./configure ${CFGOPT} "--prefix=$HOME/INSTALL_DIR" "--with-tcl=$TCL_CONFIG_PATH" || { + cat config.log + echo "::error::Failure during Configure" + exit 1 + } + env: + CFGOPT: --enable-64bit --enable-symbols=${{ matrix.symbols }} + - name: Build + run: | + make all tktest || { + echo "::error::Failure during Build" + exit 1 + } + - name: Run Tests + run: | + make test-classic | tee out-classic.txt + make test-ttk | tee out-ttk.txt + grep -q "Failed 0" out-classic.txt || { + echo "::error::Failure during Test" + exit 1 + } + grep -q "Failed 0" out-ttk.txt || { + echo "::error::Failure during Test" + exit 1 + } Index: .travis.yml ================================================================== --- .travis.yml +++ .travis.yml @@ -11,16 +11,21 @@ - gcc-mingw-w64-i686 - gcc-mingw-w64-x86-64 - gcc-multilib - tcl8.6-dev - libx11-dev + - libnotify-dev + - libglib2.0-dev + - libxss-dev - xvfb homebrew: packages: - tcl-tk - casks: - - xquartz + - libnotify + - glib +# casks: +# - xquartz jobs: include: # Testing on Linux GCC - name: "Linux/GCC/Shared" os: linux @@ -56,10 +61,20 @@ - xvfb compiler: gcc env: - BUILD_DIR=unix - CFGOPT="--disable-xft" + script: *x11gui + - name: "Linux/GCC/Shared/no-libnotify" + os: linux + dist: focal + services: + - xvfb + compiler: gcc + env: + - BUILD_DIR=unix + - CFGOPT="--disable-libnotify" script: *x11gui - name: "Linux/GCC/Shared/bionic" os: linux dist: bionic services: @@ -179,57 +194,35 @@ os: osx osx_image: xcode12 env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib CC=clang++ --enable-aqua CFLAGS=-I/usr/local/opt/tcl-tk/include CPPFLAGS=-D__private_extern__=extern" - - name: "macOS/Xcode 12/Shared" - os: osx - osx_image: xcode12 - env: - - BUILD_DIR=unix - - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua CFLAGS=-I/usr/local/opt/tcl-tk/include" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: &mactest - - make all tktest - name: "macOS/Xcode 12/Static" os: osx osx_image: xcode12 env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua --disable-shared CFLAGS=-I/usr/local/opt/tcl-tk/include" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest - name: "macOS/Xcode 12/Debug" os: osx osx_image: xcode12 env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua --enable-symbols CFLAGS=-I/usr/local/opt/tcl-tk/include" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest - - name: "macOS/Xcode 12/Shared/XQuartz" - os: osx - osx_image: xcode12 - env: - - BUILD_DIR=unix - - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --disable-corefoundation --x-includes=/opt/X11/include --x-libraries=/opt/X11/lib CFLAGS=-I/usr/local/opt/tcl-tk/include" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest +# - name: "macOS/Xcode 12/Shared/XQuartz" +# os: osx +# osx_image: xcode12 +# env: +# - BUILD_DIR=unix +# - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --disable-corefoundation --x-includes=/opt/X11/include --x-libraries=/opt/X11/lib CFLAGS=-I/usr/local/opt/tcl-tk/include" # Older MacOS versions - name: "macOS/Xcode 11/Shared" os: osx osx_image: xcode11.7 env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua CFLAGS=-I/usr/local/opt/tcl-tk/include CPPFLAGS=-mmacosx-version-min=10.14" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest - name: "macOS/Xcode 10/Shared" os: osx osx_image: xcode10.3 addons: homebrew: @@ -237,13 +230,10 @@ - tcl-tk update: true env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua CFLAGS=-I/usr/local/opt/tcl-tk/include CPPFLAGS=-mmacosx-version-min=10.14" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest - name: "macOS/Xcode 9/Shared" os: osx osx_image: xcode9.4 addons: homebrew: @@ -251,13 +241,10 @@ - tcl-tk update: true env: - BUILD_DIR=unix - CFGOPT="--with-tcl=/usr/local/opt/tcl-tk/lib --enable-aqua CFLAGS=-I/usr/local/opt/tcl-tk/include CPPFLAGS=-mmacosx-version-min=10.13" - install: - - ./configure ${CFGOPT} "--prefix=$HOME" || (cat config.log && exit 1) - script: *mactest # Test on Windows with MSVC native # - name: "Windows/MSVC/Shared" # os: windows # compiler: cl # env: &vcenv @@ -290,9 +277,17 @@ - mkdir "$HOME/install dir" - ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1) script: - make all tktest - make install +before_cache: + - |- + case $TRAVIS_OS_NAME in + osx) + brew cleanup + ;; + esac cache: directories: + - $HOME/Library/Caches/Homebrew - $HOME/AppData/Local/Temp/chocolatey - $HOME/AppData/Local/Apps/Tcl86 Index: ChangeLog ================================================================== --- ChangeLog +++ ChangeLog @@ -3201,11 +3201,11 @@ fonts to use for measurements. 2009-03-25 Jan Nijtmans * doc/wish.1: Bring doc and demos in line with - * library/demos/hello: http://wiki.tcl.tk/812 + * library/demos/hello: https://wiki.tcl-lang.org/page/exec+magic * library/demos/rmt * library/demos/square * library/demos/tcolor * library/demos/timer * library/demos/widget Index: README.md ================================================================== --- README.md +++ README.md @@ -1,32 +1,41 @@ # README: Tk -This is the **Tk 8.7a4** source distribution. +This is the **Tk 8.7a6** source distribution. You can get any source release of Tk from [our distribution site](https://sourceforge.net/projects/tcl/files/Tcl/). +8.6 (production release, daily build) +[![Build Status](https://github.com/tcltk/tk/workflows/Linux/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions?query=workflow%3A%22Linux%22+branch%3Acore-8-6-branch) +[![Build Status](https://github.com/tcltk/tk/workflows/Windows/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions?query=workflow%3A%22Windows%22+branch%3Acore-8-6-branch) +[![Build Status](https://github.com/tcltk/tk/workflows/macOS/badge.svg?branch=core-8-6-branch)](https://github.com/tcltk/tk/actions?query=workflow%3A%22macOS%22+branch%3Acore-8-6-branch) +
+8.7 (in development, daily build)) +[![Build Status](https://github.com/tcltk/tk/workflows/Linux/badge.svg?branch=main)](https://github.com/tcltk/tk/actions?query=workflow%3A%22Linux%22+branch%3Amain) +[![Build Status](https://github.com/tcltk/tk/workflows/Windows/badge.svg?branch=main)](https://github.com/tcltk/tk/actions?query=workflow%3A%22Windows%22+branch%3Amain) +[![Build Status](https://github.com/tcltk/tk/workflows/macOS/badge.svg?branch=main)](https://github.com/tcltk/tk/actions?query=workflow%3A%22macOS%22+branch%3Amain) ## 1. Introduction This directory contains the sources and documentation for Tk, a cross-platform GUI toolkit implemented with the Tcl scripting language. For details on features, incompatibilities, and potential problems with -this release, see [the Tcl/Tk 8.7 Web page](https://www.tcl.tk/software/tcltk/8.7.html) +this release, see [the Tcl/Tk 8.7 Web page](https://www.tcl-lang.org/software/tcltk/8.7.html) or refer to the "changes" file in this directory, which contains a historical record of all changes to Tk. Tk is maintained, enhanced, and distributed freely by the Tcl community. Source code development and tracking of bug reports and feature requests -takes place at [core.tcl-lang.org](https://core.tcl-lang.org/). +take place at [core.tcl-lang.org](https://core.tcl-lang.org/). Tcl/Tk release and mailing list services are [hosted by SourceForge](https://sourceforge.net/projects/tcl/) with the Tcl Developer Xchange hosted at [www.tcl-lang.org](https://www.tcl-lang.org). -Tk is a freely available open source package. You can do virtually +Tk is a freely available open-source package. You can do virtually anything you like with it, such as modifying it, redistributing it, and selling it either in whole or in part. See the file `license.terms` for complete information. ## 2. See Tcl README.md Index: changes ================================================================== --- changes +++ changes @@ -7435,11 +7435,11 @@ 2017-04-13 \u escaped content in msg files converted to true utf-8 (nijtmans) 2017-08-28 (TIP 166) Extended color notation for alpha channel (bachmann) ---- Released 8.7a1, September 8, 2017 --- http://core.tcl.tk/tk/ for details +--- Released 8.7a1, September 8, 2017 --- https://core.tcl-lang.org/tk/ for details 2017-08-24 (bug)[f1a3ca] Memory leak in [text] B-tree (edhume3) 2017-08-24 (bug)[ee40fd] Report [console] init errors (the) @@ -7720,10 +7720,154 @@ 2019-11-19 (new) Partial Emoji support in text displays (nijtmans,culler) - Released 8.6.10, Nov 21, 2019 - https://core.tcl-lang.org/tk/ for details +2019-11-25 (bug)[a95373] TkKeyEvent platform variations (werner) + +2019-11-26 (bug) workaround Win bug so test bind-34.3 passes (nijtmans) + +2019-12-03 Aqua: white cursors in dark mode (culler) + +2019-12-04 (bug)[749bd9] Aqua: systemControlAccentColor (bll,culler) + +2019-12-14 (bug)[b3b56a] ttk respect -cursor option (vogel) + +2019-12-14 (bug)[b094cb] Win: $tv -show grows widget width 1 pixel (vogel) + +2019-12-14 (bug)[02a694] spinbox options used wrong db names (vogel) + +2020-01-11 (bug)[2b8fa6] MouseWheel for ttk::scrollbar (oehlmann) + +2020-01-18 (bug)[1771594] icursor and scrollregion, canvText-14.7 (vogel) + +2020-01-18 (bug)[587937] tag list ops preserve list order (vogel) + +2020-01-18 (bug)[2830360] lose invalid state at focus event, entry-10.1 (vogel) + +2020-01-18 (bug)[077d49] string table options support null ok (vogel) + +2020-01-18 (bug)[bf93d0] Aqua: unresponsive menubar (culler) + +2020-01-31 (bug)[a196fb] restore support for unthreaded Tcl (porter,sebres) + +2020-02-09 (bug)[90a4d7] fontconfig crash when no font installed (vogel) + +2020-02-24 (bug) Aqua: incomplete floating window display (walzer) + +2020-03-11 (bug)[fb2ec3] OSX 10.15+: full screen options (nicolas,walzer) + +2020-03-12 (bug)[08e2f8] focus on unmapped windows, focus-7.1 (vogel) + +2020-03-12 (bug)[2edd84] [$c postscript] result management (gavilan) + +2020-03-22 (bug)[98662d] restore TK_MAC_DEBUG_DRAWING build (chavez) + +2020-03-29 (bug)[655fe2] tearoff menu redraw artifacts (vogel) + +2020-04-03 (bug)[efbedd] Aqua: compund button-like widget appearance (chavez) + +2020-04-14 (bug)[87bade] Aqua: improved dealing with PressAndHold (culler) + +2020-04-14 (bug)[376788] X: stop crash w/Noto Color Emoji font (nijtmans) + +2020-04-15 (bug)[89354d] Aqua: text color w/o clipping (culler) + +2020-04-15 (new) Aqua: assign Button 3 to the middle button (chavez) + +2020-04-25 (bug)[3519111] treeview horizontal scroll, entry-2.1.1 (vogel) + +2020-04-25 (bug)[141881] treeview vertical scroll, treeview-9.2 (vogel) + +2020-05-01 (bug)[2712f4] X: crash angled text w/o Xft, canvText-20.2 (vogel) + +2020-05-01 (bug)[cd8714] Win: long angled text (chavez) + +2020-05-09 (bug)[88c9e0] treeview -selectmode none focus ring (gavilan) + +2020-05-12 (new) Aqua: Rewrite of the Key event system (culler) + +2020-05-12 (bug)[411359] Aqua: stop crashes/zombies related to TouchBar (culler) + +2020-05-12 (new) Aqua: systemLinkColor (chavez) + +2020-05-16 (bug)[40ada9] crash when active button is destroyed (chavez) + +2020-05-28 (bug)[3c6660,601cea,4b50b7] Win10: ttk scale (nemethi,lanam) + +2020-06-08 (bug)[2790615] Some callbacks not eval'd in global scope (nijtmans) + +2020-06-25 Aqua: Update OSX version tests to support Big Sur (culler) + +2020-06-27 (bug)[6920b2] dup in spinbox -values causes trouble (lanam) + +2020-06-27 (bug)[5c51be] invalid mem read buffer in Tk_PhotoPut* (chavez) + +2020-06-27 (bug)[16ef16] restore bind sequence support, bind-33.(16-21) (vogel) + +2020-07-02 (bug)[2d2459] default style for combobox (bll) + +2020-07-06 (bug)[40e4bf] double free, entry-19.21 (vogel) + +2020-07-06 (bug)[e3888d] grab & warp, bind-36.1 (vogel) + +2020-07-12 (bug)[2442314] fontchooser i18n (nijtmans) + +2020-07-13 (bug)[7655f6] [*entry]: selected text drawing reform (chavez) + +2020-07-14 (bug)[09abd7] workaround invalid key codes from Debian 10 (vogel) + +2020-07-20 (bug)[cf3853] Aqua: improve bounds on non-Retina displays (chavez) + +2020-08-01 Aqua: [winfo rgb] light and dark mode support (culler) + +2020-08-15 (bug)[315104] Aqua: appearance change virtual events (culler) + +2020-08-21 (bug)[291699] mouse binding for scrollbar grip (bll) + +2020-09-08 (bug)[6c2425] buffer bounds violation (chavez) + +2020-09-08 (bug)[2a6d63] OSX 10.6 crash (hellstrom,culler) + +2020-09-08 (bug)[420feb] undefined behavior due to alignment (chavez,nijtmans) + +2020-09-10 (bug)[ab1fea] Aqua init issues (culler) + +2020-09-14 (bug)[71e18c] Aqua: crash in full screen toggle (culler) + +2020-09-18 (bug)[4f4f03] Aqua: mouse drags across title bar (nab,culler) + +2020-09-21 (bug)[d91e05] select/copy in disabled text (bll) + +2020-09-27 (TIP #581) disfavor Master/Slave terminology (nijtmans) + +2020-09-30 (bug)[59cba3] win: improve theme detection (bll,nijtmans) + +2020-10-06 (bug)[175a6e] Aqua: support tiled windows (culler) + +2020-10-07 (bug)[1fa8c3] Aqua: crash on resize during display (nab,culler) + +2020-10-16 (bug)[c2483b] Aqua: consistent finalization (culler,nijtmans) + +2020-11-06 (bug)[c9ebac] Aqua: use standard about dialog (culler) + +2020-11-07 (bug)[4ebcc0] sticky fontchooser options (roseman,vogel) + +2020-11-10 (bug)[f9fa92] Aqua: crash in color caching scheme (culler) + +2020-11-20 (bug)[7185d2] Aqua: fixes to special menu support (culler) + +2020-11-24 (bug)[4a40c6] Aqua: [wm manage] frame offset (chavez) + +2020-12-04 (bug)[3ef77f] Aqua dark mode combobox focus ring (walzer,culler) + +2020-12-15 (bug)[80e4c6] Aqua: progressbar animation (nab,culler) + +2020-12-24 (bug)[6157a8] Aqua: file dialog -filetypes (davis,culler) + +- Released 8.6.11, Dec 31, 2020 - https://core.tcl-lang.org/tk/ for details + Changes to 8.7a3 include all changes to the 8.6 line through 8.6.10, plus the following, which focuses on the high-level feature changes in this changeset (new minor version) rather than bug fixes: 2017-11-25 [TIP 161] $menu -tearoff default changed to false (roseman,vogel) @@ -7739,11 +7883,11 @@ 2018-11-03 [TIP 512] Deprecate stub for Tk_MainEx() (nijtmans) 2018-11-06 [TIP 415] New option -height for [$canvas create arc] (geard) -2018-11-06 [TIP 518] New event <> (oehlmann) +2018-11-06 [TIP 518] New event <> (oehlmann) 2019-04-14 [TIP 164] New subcommand [$canvas rotate] (fellows) 2019-04-14 [TIP 507] New photo image format 'svg' (zaumseil) @@ -7755,6 +7899,83 @@ 2019-06-15 [TIP 528] Deprecate Tk_Offset() (nijtmans) 2019-08-19 [TIP 545] Revised options for photo image format 'svg' (oehlmann) ---- Released 8.7a3, November 25, 2019 --- http://core.tcl.tk/tk/ for details +--- Released 8.7a3, November 25, 2019 --- https://core.tcl-lang.org/tk/ for details + +Changes to 8.7a5 include all changes to the 8.6 line through 8.6.11, +plus the following, which focuses on the high-level feature changes +in this changeset (new minor version) rather than bug fixes: + +2020-02-22 [TIP 565] Gracefully ignore non-existent tags in canvas raise/lower + +2020-02-22 [TIP 564] Specify ttk font sizes in points on X11 + +2020-02-24 [TIP 563] Scrollwheel on Horizontal Scrollbar Scrolls Without Shift too + +2020-02-28 [TIP 557] C++ support + +2020-03-12 (bug)[355180] solve XKeycodeToKeysym deprecation + *** POTENTIAL INCOMPATIBILITY -- Tk 8.7 now requires X11R6 *** + +2020-03-18 [TIP 569] Eliminate comments that serve lint + +2020-05-17 [d87dc2] Remove TkMacOSXGetStringObjFromCFString() + +2020-05-24 [TIP 574] Add a 'tag delete' command to the ttk::treeview widget + +2020-06-27 (bug)[50ed1e] spinbox with duplicate values + +2020-07-03 [TIP 578] Death to TCL_DBGX + +2020-08-23 (bug)[bb85d2] valgrind on TIP 489 + +2020-08024 (bug)[d30c21] default colors for TIP 496 + +2020-09-02 [TIP 580] Export Tk_GetDoublePixelsFromObj and 5 more + +2020-10-21 [TIP 474] Uniform mouse wheel events + +2020-11-15 [TIP 584] Better introspection for ttk + +2020-11-16 [TIP 588] Unicode for (X11) keysyms + +2020-12-03 [TIP 590] Recommend lowercase package names + +2020-12-09 (bug)[d6e9b4] SVG memory overflow + +2020-12-11 [TIP 591] Rotate ttk::notebook window with mousewheel on tab + +2020-12-12 [TIP 325] System tray and system notification + +2021-01-08 [TIP 592] End support: Windows XP, Server 2003, Vista, Server 2008 + +2021-01-08 (bug)[822330] Prevent buffer overflow in SVG image. + +2021-01-28 (bug)[237971] 'end' argument to [$canvas insert] + +2021-02-25 (bug)[be9cad] crash in [tkwait] + +2021-02-27 [TIP 529] Add metadata dictionary property to tk photo image + +2021-03-02 (bug)[1626ed] Aqua crash: dead keys as meny accelerator + +2021-03-29 (bug)[9b6065] Restore Tcl [update] when Tk is destroyed + +2021-04-08 (bug)[58222c] background colors + +2021-04-09 [TIP 595] Unicode-aware/case-sensitive Loadable Library handling + +2021-04-21 (bug)[cde766] update scrollbars on treeview + +2021-04-26 (bug)[c97464] memleak in aqua fonts + +2021-05-02 (bug)[2ecb09] Follow Mac OSX Key-repeat setting + +2021-05-03 (bug)[8a5086] ttk::entry issue + +2021-05-22 (bug)[3e3360] bind substitution %S + +2021-05-25 (bug)[7bda98] aqua: double click bind with changing focus + +- Released 8.7a5, Jun 18, 2021 --- https://core.tcl-lang.org/tcl/ for details - Index: doc/AddOption.3 ================================================================== --- doc/AddOption.3 +++ doc/AddOption.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tk_AddOption 3 "" Tk "Tk Library Procedures" .so man.macros .BS Index: doc/CrtPhImgFmt.3 ================================================================== --- doc/CrtPhImgFmt.3 +++ doc/CrtPhImgFmt.3 @@ -7,28 +7,36 @@ '\" '\" Author: Paul Mackerras (paulus@cs.anu.edu.au), '\" Department of Computer Science, '\" Australian National University. '\" -.TH Tk_CreatePhotoImageFormat 3 8.5 Tk "Tk Library Procedures" +.TH Tk_CreatePhotoImageFormat 3 8.7 Tk "Tk Library Procedures" .so man.macros .BS .SH NAME Tk_CreatePhotoImageFormat \- define new file format for photo images .SH SYNOPSIS .nf \fB#include \fR +.sp +.VS 8.7 +\fBTk_CreatePhotoImageFormatVersion3\fR(\fIformatVersion3Ptr\fR) +.VE 8.7 .sp \fBTk_CreatePhotoImageFormat\fR(\fIformatPtr\fR) .SH ARGUMENTS -.AS "const Tk_PhotoImageFormat" *formatPtr +.AS "const Tk_PhotoImageFormatVersion3" *formatVersion3Ptr +.VS 8.7 +.AP "const Tk_PhotoImageFormatVersion3" *formatVersion3Ptr in +Structure that defines the new file format including metadata functionality. +.VE 8.7 .AP "const Tk_PhotoImageFormat" *formatPtr in Structure that defines the new file format. .BE .SH DESCRIPTION .PP -\fBTk_CreatePhotoImageFormat\fR is invoked to define a new file format +\fBTk_CreatePhotoImageFormatVersion3\fR is invoked to define a new file format for image data for use with photo images. The code that implements an image file format is called an image file format handler, or handler for short. The photo image code maintains a list of handlers that can be used to read and write data to or from a file. Some handlers may also @@ -35,27 +43,34 @@ support reading image data from a string or converting image data to a string format. The user can specify which handler to use with the \fB\-format\fR image configuration option or the \fB\-format\fR option to the \fBread\fR and \fBwrite\fR photo image subcommands. +.PP +The alternate version 2 function \fBTk_CreatePhotoImageFormat\fR has +identical functionality, but does not allow the handler to get or return +the metadata dictionary of the image. +It is described in section \fBVERSION 2 INTERFACE\fR below. .PP An image file format handler consists of a collection of procedures -plus a Tk_PhotoImageFormat structure, which contains the name of the -image file format and pointers to six procedures provided by the -handler to deal with files and strings in this format. The -Tk_PhotoImageFormat structure contains the following fields: +plus a \fBTk_PhotoImageFormatVersion3\fR structure, which contains the +name of the image file format and pointers to six procedures provided +by the handler to deal with files and strings in this format. The +Tk_PhotoImageFormatVersion3 structure contains the following fields: +.VS 8.7 .CS -typedef struct Tk_PhotoImageFormat { +typedef struct Tk_PhotoImageFormatVersion3 { const char *\fIname\fR; - Tk_ImageFileMatchProc *\fIfileMatchProc\fR; - Tk_ImageStringMatchProc *\fIstringMatchProc\fR; - Tk_ImageFileReadProc *\fIfileReadProc\fR; - Tk_ImageStringReadProc *\fIstringReadProc\fR; - Tk_ImageFileWriteProc *\fIfileWriteProc\fR; - Tk_ImageStringWriteProc *\fIstringWriteProc\fR; -} \fBTk_PhotoImageFormat\fR; + Tk_ImageFileMatchProcVersion3 *\fIfileMatchProc\fR; + Tk_ImageStringMatchProcVersion3 *\fIstringMatchProc\fR; + Tk_ImageFileReadProcVersion3 *\fIfileReadProc\fR; + Tk_ImageStringReadProcVersion3 *\fIstringReadProc\fR; + Tk_ImageFileWriteProcVersion3 *\fIfileWriteProc\fR; + Tk_ImageStringWriteProcVersion3 *\fIstringWriteProc\fR; +} \fBTk_PhotoImageFormatVersion3\fR; .CE +.VE 8.7 .PP The handler need not provide implementations of all six procedures. For example, the procedures that handle string data would not be provided for a format in which the image data are stored in binary, and could therefore contain null characters. If any procedure is not @@ -65,58 +80,68 @@ procedure, and the \fIstringMatchProc\fR procedure if it provides the \fIstringReadProc\fR procedure. .SS NAME .PP \fIformatPtr->name\fR provides a name for the image type. -Once \fBTk_CreatePhotoImageFormat\fR returns, this name may be used -in the \fB\-format\fR photo image configuration and subcommand option. +Once \fBTk_CreatePhotoImageFormatVersion3\fR returns, this name may be +used in the \fB\-format\fR photo image configuration and subcommand +option. The manual page for the photo image (photo(n)) describes how image file formats are chosen based on their names and the value given to the \fB\-format\fR option. The first character of \fIformatPtr->name\fR must not be an uppercase character from the ASCII character set (that is, one of the characters \fBA\fR-\fBZ\fR). Such names are used only for legacy interface support (see below). +.VS 8.7 .SS FILEMATCHPROC .PP \fIformatPtr->fileMatchProc\fR provides the address of a procedure for Tk to call when it is searching for an image file format handler suitable for reading data in a given file. \fIformatPtr->fileMatchProc\fR must match the following prototype: .CS -typedef int \fBTk_ImageFileMatchProc\fR( +typedef int \fBTk_ImageFileMatchProcVersion3\fR( + Tcl_Interp *\fIinterp\fR, Tcl_Channel \fIchan\fR, const char *\fIfileName\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, int *\fIwidthPtr\fR, int *\fIheightPtr\fR, - Tcl_Interp *\fIinterp\fR); + Tcl_Obj *\fImetadataOut\fR); .CE The \fIfileName\fR argument is the name of the file containing the image data, which is open for reading as \fIchan\fR. The \fIformat\fR argument contains the value given for the \fB\-format\fR option, or NULL if the option was not specified. +\fBmetadataIn\fR and \fBmetadataOut\fR inputs and returns a metadata +dictionary as described in section \fBMETADATA INTERFACE\fR below. If the data in the file appears to be in the format supported by this handler, the \fIformatPtr->fileMatchProc\fR procedure should store the width and height of the image in *\fIwidthPtr\fR and *\fIheightPtr\fR respectively, and return 1. Otherwise it should return 0. .SS STRINGMATCHPROC .PP -\fIformatPtr->stringMatchProc\fR provides the address of a procedure for -Tk to call when it is searching for an image file format handler for +\fIformatPtr->stringMatchProc\fR provides the address of a procedure +for Tk to call when it is searching for an image file format handler suitable for reading data from a given string. \fIformatPtr->stringMatchProc\fR must match the following prototype: .CS -typedef int \fBTk_ImageStringMatchProc\fR( +typedef int \fBTk_ImageStringMatchProcVersion3\fR( + Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIdata\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, int *\fIwidthPtr\fR, int *\fIheightPtr\fR, - Tcl_Interp *\fIinterp\fR); + Tcl_Obj *\fImetadataOut\fR); .CE The \fIdata\fR argument points to the object containing the image data. The \fIformat\fR argument contains the value given for the \fB\-format\fR option, or NULL if the option was not specified. +\fBmetadataIn\fR and \fBmetadataOut\fR inputs and returns a metadata +dictionary as described in section \fBMETADATA INTERFACE\fR below. If the data in the string appears to be in the format supported by this handler, the \fIformatPtr->stringMatchProc\fR procedure should store the width and height of the image in *\fIwidthPtr\fR and *\fIheightPtr\fR respectively, and return 1. Otherwise it should return 0. @@ -129,14 +154,16 @@ typedef int \fBTk_ImageFileReadProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Channel \fIchan\fR, const char *\fIfileName\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, PhotoHandle \fIimageHandle\fR, int \fIdestX\fR, int \fIdestY\fR, int \fIwidth\fR, int \fIheight\fR, - int \fIsrcX\fR, int \fIsrcY\fR); + int \fIsrcX\fR, int \fIsrcY\fR, + Tcl_Obj *\fImetadataOut\fR); .CE The \fIinterp\fR argument is the interpreter in which the command was invoked to read the image; it should be used for reporting errors. The image data is in the file named \fIfileName\fR, which is open for reading as \fIchan\fR. The \fIformat\fR argument contains the @@ -146,38 +173,44 @@ \fIimageHandle\fR. The subimage of the data in the file is of dimensions \fIwidth\fR x \fIheight\fR and has its top-left corner at coordinates (\fIsrcX\fR,\fIsrcY\fR). It is to be stored in the photo image with its top-left corner at coordinates (\fIdestX\fR,\fIdestY\fR) using the \fBTk_PhotoPutBlock\fR procedure. +\fBmetadataIn\fR and \fBmetadataOut\fR inputs and returns a metadata +dictionary as described in section \fBMETADATA INTERFACE\fR below. The return value is a standard Tcl return value. .SS STRINGREADPROC .PP -\fIformatPtr->stringReadProc\fR provides the address of a procedure for -Tk to call to read data from a string into a photo image. +\fIformatPtr->stringReadProc\fR provides the address of a procedure +for Tk to call to read data from a string into a photo image. \fIformatPtr->stringReadProc\fR must match the following prototype: .CS typedef int \fBTk_ImageStringReadProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIdata\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, PhotoHandle \fIimageHandle\fR, int \fIdestX\fR, int \fIdestY\fR, int \fIwidth\fR, int \fIheight\fR, - int \fIsrcX\fR, int \fIsrcY\fR); + int \fIsrcX\fR, int \fIsrcY\fR, + Tcl_Obj *\fImetadataOut\fR); .CE The \fIinterp\fR argument is the interpreter in which the command was invoked to read the image; it should be used for reporting errors. The \fIdata\fR argument points to the image data in object form. The \fIformat\fR argument contains the value given for the \fB\-format\fR option, or NULL if the option was -not specified. The image data in the string, or a subimage of it, is to -be read into the photo image identified by the handle +not specified. The image data in the string, or a subimage of it, is +to be read into the photo image identified by the handle \fIimageHandle\fR. The subimage of the data in the string is of dimensions \fIwidth\fR x \fIheight\fR and has its top-left corner at coordinates (\fIsrcX\fR,\fIsrcY\fR). It is to be stored in the photo image with its top-left corner at coordinates (\fIdestX\fR,\fIdestY\fR) using the \fBTk_PhotoPutBlock\fR procedure. +\fBmetadataIn\fR and \fBmetadataOut\fR inputs and returns a metadata +dictionary as described in section \fBMETADATA INTERFACE\fR below. The return value is a standard Tcl return value. .SS FILEWRITEPROC .PP \fIformatPtr->fileWriteProc\fR provides the address of a procedure for Tk to call to write data from a photo image to a file. @@ -185,10 +218,11 @@ .CS typedef int \fBTk_ImageFileWriteProc\fR( Tcl_Interp *\fIinterp\fR, const char *\fIfileName\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, Tk_PhotoImageBlock *\fIblockPtr\fR); .CE The \fIinterp\fR argument is the interpreter in which the command was invoked to write the image; it should be used for reporting errors. The image data to be written are in memory and are described by the @@ -199,20 +233,24 @@ value given for the \fB\-format\fR option, or NULL if the option was not specified. The format string can contain extra characters after the name of the format. If appropriate, the \fIformatPtr->fileWriteProc\fR procedure may interpret these characters to specify further details about the image file. +\fBmetadataIn\fR may contain metadata keys that a driver may include +into the output data. The return value is a standard Tcl return value. .SS STRINGWRITEPROC .PP -\fIformatPtr->stringWriteProc\fR provides the address of a procedure for -Tk to call to translate image data from a photo image into a string. +\fIformatPtr->stringWriteProc\fR provides the address of a procedure +for Tk to call to translate image data from a photo image into a +string. \fIformatPtr->stringWriteProc\fR must match the following prototype: .CS typedef int \fBTk_ImageStringWriteProc\fR( Tcl_Interp *\fIinterp\fR, Tcl_Obj *\fIformat\fR, + Tcl_Obj *\fImetadataIn\fR, Tk_PhotoImageBlock *\fIblockPtr\fR); .CE The \fIinterp\fR argument is the interpreter in which the command was invoked to convert the image; it should be used for reporting errors. The image data to be converted are in memory and are described by the @@ -223,11 +261,205 @@ value given for the \fB\-format\fR option, or NULL if the option was not specified. The format string can contain extra characters after the name of the format. If appropriate, the \fIformatPtr->stringWriteProc\fR procedure may interpret these characters to specify further details about the image file. +\fBmetadataIn\fR may contain metadata keys that a driver may include +into the output data. The return value is a standard Tcl return value. +.PP +.SH "METADATA INTERFACE" +.PP +Image formats contain a description of the image bitmap and may +contain additional information like image resolution or comments. +Image metadata may be read from image files and passed to the script +level by including dictionary keys into the metadata property of the +image. Image metadata may be written to image data on file write or +image data output. +.PP +.PP +.SS "METADATA KEYS" +.PP +The metadata may contain any key. +A driver will handle only a set of dictionary keys documented in the +documentation. See the photo image manual page for currently defined +keys for the system drivers. +.PP +The following rules may give guidance to name metadata keys: +.RS +Abreviation are in upper case +.RE +.RS +Words are in US English in small case (except proper nouns) +.RE +.RS +Vertical DPI is expressed as DPI/aspect. The reason is, that some +image formats may feature aspect and no resolution value. +.RE +.SS "METADATA INPUT" +.PP +Each driver function gets a Tcl object pointer \fBmetadataIn\fR as +parameter. This parameter serves to input a metadata dict to the +driver function. +It may be NULL to flag that the metadata dict is empty. +.PP +A typical driver code snipped to check for a metadata key is: +.CS +if (NULL != metadataIn) { + Tcl_Obj *itemData; + Tcl_DictObjGet(interp, metadataIn, Tcl_NewStringObj("Comment",-1), &itemData)); +.CE +.PP +The \-metadata command option data of the following commands is passed +to the driver: \fBimage create\fR, \fBconfigure\fR, \fBput\fR, +\fBread\fR, \fBdata\fR and \fBwrite\fR. +If no \-metadata command option available or not given, the metadata +property of the image is passed to the driver using the following +commands: \fBcget\fR, \fBconfigure\fR, \fBdata\fR and \fBwrite\fR. +.PP +Note that setting the \-metadata property of an image using +\fBconfigure\fR without any other option does not invoke any driver +function. +.PP +The metadata dictionary is not suited to pass options to the driver +related to the bitmap representation, as the image bitmap is not +recreated on a metadata change. The format string should be used for +this purpose. +.PP +.SS "METADATA OUTPUT" +.PP +The image match and read driver functions may set keys in a prepared +matadata dict to return them. +Those functions get a Tcl object pointer \fBmetadataOut\fR as +parameter. +metadataOut may be NULL to indicate, that no metadata return is +attended(\fBput\fR, \fBread\fR subcommands). +\fBmetadataOut\fR is initialized to an empty unshared dict object if +metadata return is attended (\fBimage create\fR command, \fBconfigure\fR +subcommand). The driver may set dict keys in this object to return +metadata. +If a match function succeeds, the metadataOut pointer is passed to the +corresponding read function. +.PP +A sample driver code snippet is: +.CS +if (NULL != metadataOut) { + Tcl_DictObjPut(NULL, metadataOut, Tcl_NewStringObj("XMP",-1), Tcl_NewStringObj(xmpMetadata); +.CE +.PP +The metadata keys returned by the driver are merged into the present +metadata property of the image or into the metadata dict given by the +\fB\-metadata\fR command line option. +At the script level, the command \fBimage create\fR and the +\fBconfigure\fR method may return metadata from the driver. +.PP +Format string options or metadata keys may influence the creation of +metadata within the driver. +For example, the creation of an expensive metadata key may depend on a +format string option or on a metadata input key. +.PP +.VE 8.7 +.SH "VERSION 2 INTERFACE" +.PP +Version 2 Interface does not include the possibility for the driver to +use the metadata dict for input or output. +.SS SYNOPSIS +\fB#include \fR +.sp +\fBTk_CreatePhotoImageFormat\fR(\fIformatPtr\fR) +.SS ARGUMENTS +.AS "const Tk_PhotoImageFormat" *formatPtr +.AP "const Tk_PhotoImageFormat" *formatPtr in +Structure that defines the new file format. +.BE +.SS DESCRIPTION +A driver using the version 2 interface invokes \fBTk_CreatePhotoImageFormat\fR +for driver registration. The Tk_PhotoImageFormat structure +contains the following fields: +.CS +typedef struct Tk_PhotoImageFormat { + const char *\fIname\fR; + Tk_ImageFileMatchProc *\fIfileMatchProc\fR; + Tk_ImageStringMatchProc *\fIstringMatchProc\fR; + Tk_ImageFileReadProc *\fIfileReadProc\fR; + Tk_ImageStringReadProc *\fIstringReadProc\fR; + Tk_ImageFileWriteProc *\fIfileWriteProc\fR; + Tk_ImageStringWriteProc *\fIstringWriteProc\fR; +} \fBTk_PhotoImageFormat\fR; +.CE +.PP +.SS FILEMATCHPROC +.PP +\fIformatPtr->fileMatchProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageFileMatchProc\fR( + Tcl_Channel \fIchan\fR, + const char *\fIfileName\fR, + Tcl_Obj *\fIformat\fR, + int *\fIwidthPtr\fR, + int *\fIheightPtr\fR, + Tcl_Interp *\fIinterp\fR); +.CE +.PP +.SS STRINGMATCHPROC +.PP +\fIformatPtr->stringMatchProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageStringMatchProc\fR( + Tcl_Obj *\fIdata\fR, + Tcl_Obj *\fIformat\fR, + int *\fIwidthPtr\fR, + int *\fIheightPtr\fR, + Tcl_Interp *\fIinterp\fR); +.CE +.SS FILEREADPROC +.PP +\fIformatPtr->fileReadProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageFileReadProc\fR( + Tcl_Interp *\fIinterp\fR, + Tcl_Channel \fIchan\fR, + const char *\fIfileName\fR, + Tcl_Obj *\fIformat\fR, + PhotoHandle \fIimageHandle\fR, + int \fIdestX\fR, int \fIdestY\fR, + int \fIwidth\fR, int \fIheight\fR, + int \fIsrcX\fR, int \fIsrcY\fR); +.CE +.SS STRINGREADPROC +.PP +\fIformatPtr->stringReadProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageStringReadProc\fR( + Tcl_Interp *\fIinterp\fR, + Tcl_Obj *\fIdata\fR, + Tcl_Obj *\fIformat\fR, + PhotoHandle \fIimageHandle\fR, + int \fIdestX\fR, int \fIdestY\fR, + int \fIwidth\fR, int \fIheight\fR, + int \fIsrcX\fR, int \fIsrcY\fR); +.CE +.SS FILEWRITEPROC +.PP +\fIformatPtr->fileWriteProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageFileWriteProc\fR( + Tcl_Interp *\fIinterp\fR, + const char *\fIfileName\fR, + Tcl_Obj *\fIformat\fR, + Tk_PhotoImageBlock *\fIblockPtr\fR); +.CE +.SS STRINGWRITEPROC +.PP +\fIformatPtr->stringWriteProc\fR must match the following prototype: +.CS +typedef int \fBTk_ImageStringWriteProc\fR( + Tcl_Interp *\fIinterp\fR, + Tcl_Obj *\fIformat\fR, + Tk_PhotoImageBlock *\fIblockPtr\fR); +.CE +.PP .SH "LEGACY INTERFACE SUPPORT" .PP In Tk 8.2 and earlier, the definition of all the function pointer types stored in fields of a \fBTk_PhotoImageFormat\fR struct were incompatibly different. Legacy programs and libraries dating from Index: doc/GetHINSTANCE.3 ================================================================== --- doc/GetHINSTANCE.3 +++ doc/GetHINSTANCE.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tk_GetHISTANCE 3 "" Tk "Tk Library Procedures" .so man.macros .BS Index: doc/GetHWND.3 ================================================================== --- doc/GetHWND.3 +++ doc/GetHWND.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH HWND 3 8.0 Tk "Tk Library Procedures" .so man.macros .BS Index: doc/Grab.3 ================================================================== --- doc/Grab.3 +++ doc/Grab.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tk_Grab 3 "" Tk "Tk Library Procedures" .so man.macros .BS Index: doc/HWNDToWindow.3 ================================================================== --- doc/HWNDToWindow.3 +++ doc/HWNDToWindow.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tk_HWNDToWindow 3 "" Tk "Tk Library Procedures" .so man.macros .BS Index: doc/Inactive.3 ================================================================== --- doc/Inactive.3 +++ doc/Inactive.3 @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH Tk_GetUserInactiveTime 3 8.5 Tk "Tk Library Procedures" .so man.macros .BS Index: doc/TextLayout.3 ================================================================== --- doc/TextLayout.3 +++ doc/TextLayout.3 @@ -106,12 +106,13 @@ .AP int lastChar in The index of the last character up to which to draw. The character specified by \fIlastChar\fR itself will not be drawn. A number less than 0 means to draw all characters in the text layout. .AP int underline in -Index of the single character to underline in the text layout, or a number -less than 0 for no underline. +Index of the single character to underline in the text layout, or a +negative number counting backwards from the end of the string. Any +out-of-range number (e.g. INT_MIN) means no underline. .AP int index in The index of the character whose bounding box is desired. The bounding box is computed with respect to the upper-left hand corner of the text layout. .AP int "*xPtr, *yPtr" out Filled with the upper-left hand corner, in pixels, of the bounding box Index: doc/bind.n ================================================================== --- doc/bind.n +++ doc/bind.n @@ -1,9 +1,9 @@ '\" '\" Copyright (c) 1990 The Regents of the University of California. '\" Copyright (c) 1994-1996 Sun Microsystems, Inc. -'\" Copyright (c) 1998 by Scriptics Corporation. +'\" Copyright (c) 1998 Scriptics Corporation. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH bind n 8.0 Tk "Tk Built-In Commands" Index: doc/chooseDirectory.n ================================================================== --- doc/chooseDirectory.n +++ doc/chooseDirectory.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH tk_chooseDirectory n 8.3 Tk "Tk Built-In Commands" .so man.macros .BS Index: doc/colors.n ================================================================== --- doc/colors.n +++ doc/colors.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" Copyright (c) 2003 ActiveState Corporation. '\" Copyright (c) 2006-2007 Daniel A. Steffen '\" Copyright (c) 2008 Donal K. Fellows '\" .TH colors n 8.3 Tk "Tk Built-In Commands" Index: doc/console.n ================================================================== --- doc/console.n +++ doc/console.n @@ -21,11 +21,11 @@ Tk toolkit loaded, and control over this interpreter is given through the \fBconsole\fR command. The behaviour of the console window is defined mainly through the contents of the \fIconsole.tcl\fR file in the Tk library. Except for TkAqua, this command is not available when Tk is loaded into a tclsh interpreter with -.QW "\fBpackage require Tk\fR" , +.QW "\fBpackage require tk\fR" , as a conventional terminal is expected to be present in that case. In TkAqua, this command is disabled when there is a startup script and stdin is \fB/dev/null\fR (as is the case e.g. when a bundled application embedding Tk is started by the macOS Launcher). To enable the command in that case, define the environment variable \fBTK_CONSOLE\fR. This can be Index: doc/cursors.n ================================================================== --- doc/cursors.n +++ doc/cursors.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" '\" Copyright (c) 2006-2007 Daniel A. Steffen '\" .TH cursors n 8.3 Tk "Tk Built-In Commands" Index: doc/event.n ================================================================== --- doc/event.n +++ doc/event.n @@ -340,10 +340,19 @@ .TP \fB<>\fR This is sent to all widgets when the ttk theme changed. The ttk widgets listen to this event and redisplay themselves when it fires. The legacy widgets ignore this event. +.TP +\fB<>\fR +. +This event is sent to all widgets when a font is changed, for example, +by the use of [font configure]. The user_data field (%d) will have the +value "FontChanged". For other system wide changes, this event will +be sent to all widgets, and the user_data field will indicate the +cause of the change. NOTE: all tk and ttk widgets already handle this +event internally. .TP \fB<>\fR This is sent to a widget when the focus enters the widget because of a user-driven .QW "tab to widget" Index: doc/grid.n ================================================================== --- doc/grid.n +++ doc/grid.n @@ -309,11 +309,11 @@ causes only the content in the row (or column) specified by \fIvalue\fR to be returned. .TP \fBgrid slaves \fIwindow\fR ?\fI\-option value\fR? . -Synonym for . \fBgrid content \fIwindow\fR ?\fI\-option value\fR? +Synonym for \fBgrid content \fIwindow\fR ?\fI\-option value\fR?. .SH "RELATIVE PLACEMENT" .PP The \fBgrid\fR command contains a limited set of capabilities that permit layouts to be created without specifying the row and column information for each content. This permits content to be rearranged, Index: doc/keysyms.n ================================================================== --- doc/keysyms.n +++ doc/keysyms.n @@ -1,7 +1,7 @@ '\" -'\" Copyright (c) 1998-2000 by Scriptics Corporation. +'\" Copyright (c) 1998-2000 Scriptics Corporation. '\" All rights reserved. '\" .TH keysyms n 8.3 Tk "Tk Built-In Commands" .so man.macros .BS @@ -10,11 +10,11 @@ keysyms \- keysyms recognized by Tk .BE .SH DESCRIPTION .PP Tk recognizes many keysyms when specifying key bindings (e.g., -.QW "\fBbind\fR \fB. \fR" ). +.QW "\fBbind\fR \fB. <\fR\fIkeysym\fR\fB>\fR" ). The following list enumerates the keysyms that will be recognized by Tk. Note that not all keysyms will be valid on all platforms, and some keysyms are also available on platforms that have a different native name for that key. For example, on Unix systems, the presence @@ -22,25 +22,25 @@ keyboard modifier map. This list shows keysyms along with their decimal and hexadecimal values. .PP .CS space 32 0x20 -exclam 33 0x21 +! (exclam) 33 0x21 quotedbl 34 0x22 numbersign 35 0x23 dollar 36 0x24 -percent 37 0x25 -ampersand 38 0x26 -apostrophe 39 0x27 -parenleft 40 0x28 -parenright 41 0x29 -asterisk 42 0x2A -plus 43 0x2B -comma 44 0x2C +% (percent) 37 0x25 +& (ampersand) 38 0x26 +' (apostrophe) 39 0x27 +( (parenleft) 40 0x28 +) (parenright) 41 0x29 +* (asterisk) 42 0x2A ++ (plus) 43 0x2B +, (comma) 44 0x2C minus 45 0x2D -period 46 0x2E -slash 47 0x2F +. (period) 46 0x2E +/ (slash) 47 0x2F 0 48 0x30 1 49 0x31 2 50 0x32 3 51 0x33 4 52 0x34 @@ -47,17 +47,17 @@ 5 53 0x35 6 54 0x36 7 55 0x37 8 56 0x38 9 57 0x39 -colon 58 0x3A +: (colon) 58 0x3A semicolon 59 0x3B less 60 0x3C -equal 61 0x3D += (equal) 61 0x3D greater 62 0x3E -question 63 0x3F -at 64 0x40 +? (question) 63 0x3F +@ (at) 64 0x40 A 65 0x41 B 66 0x42 C 67 0x43 D 68 0x44 E 69 0x45 @@ -83,13 +83,13 @@ Y 89 0x59 Z 90 0x5A bracketleft 91 0x5B backslash 92 0x5C bracketright 93 0x5D -asciicircum 94 0x5E -underscore 95 0x5F -grave 96 0x60 +^ (asciicircum) 94 0x5E +_ (underscore) 95 0x5F +` (grave) 96 0x60 a 97 0x61 b 98 0x62 c 99 0x63 d 100 0x64 e 101 0x65 @@ -113,120 +113,120 @@ w 119 0x77 x 120 0x78 y 121 0x79 z 122 0x7A braceleft 123 0x7B -bar 124 0x7C +| (bar) 124 0x7C braceright 125 0x7D -asciitilde 126 0x7E +~ (asciitilde) 126 0x7E nobreakspace 160 0xA0 -exclamdown 161 0xA1 -cent 162 0xA2 -sterling 163 0xA3 -currency 164 0xA4 -yen 165 0xA5 -brokenbar 166 0xA6 -section 167 0xA7 -diaeresis 168 0xA8 -copyright 169 0xA9 -ordfeminine 170 0xAA -guillemotleft 171 0xAB -notsign 172 0xAC +\(r! (exclamdown) 161 0xA1 +\(ct (cent) 162 0xA2 +\(Po (sterling) 163 0xA3 +\(Cs (currency) 164 0xA4 +\(Ye (yen) 165 0xA5 +\(bb (brokenbar) 166 0xA6 +\(sc (section) 167 0xA7 +\(ad (diaeresis) 168 0xA8 +\(co (copyright) 169 0xA9 +\(Of (ordfeminine) 170 0xAA +\(Fo (guillemotleft) 171 0xAB +\(no (notsign) 172 0xAC hyphen 173 0xAD -registered 174 0xAE -macron 175 0xAF -degree 176 0xB0 -plusminus 177 0xB1 -twosuperior 178 0xB2 -threesuperior 179 0xB3 -acute 180 0xB4 -mu 181 0xB5 -paragraph 182 0xB6 -periodcentered 183 0xB7 -cedilla 184 0xB8 -onesuperior 185 0xB9 -masculine 186 0xBA -guillemotright 187 0xBB -onequarter 188 0xBC -onehalf 189 0xBD -threequarters 190 0xBE -questiondown 191 0xBF -Agrave 192 0xC0 -Aacute 193 0xC1 -Acircumflex 194 0xC2 -Atilde 195 0xC3 -Adiaeresis 196 0xC4 -Aring 197 0xC5 -AE 198 0xC6 -Ccedilla 199 0xC7 -Egrave 200 0xC8 -Eacute 201 0xC9 -Ecircumflex 202 0xCA -Ediaeresis 203 0xCB -Igrave 204 0xCC -Iacute 205 0xCD -Icircumflex 206 0xCE -Idiaeresis 207 0xCF -ETH 208 0xD0 -Ntilde 209 0xD1 -Ograve 210 0xD2 -Oacute 211 0xD3 -Ocircumflex 212 0xD4 -Otilde 213 0xD5 -Odiaeresis 214 0xD6 -multiply 215 0xD7 -Oslash 216 0xD8 -Ugrave 217 0xD9 -Uacute 218 0xDA -Ucircumflex 219 0xDB -Udiaeresis 220 0xDC -Yacute 221 0xDD -THORN 222 0xDE -ssharp 223 0xDF -agrave 224 0xE0 -aacute 225 0xE1 -acircumflex 226 0xE2 -atilde 227 0xE3 -adiaeresis 228 0xE4 -aring 229 0xE5 -ae 230 0xE6 -ccedilla 231 0xE7 -egrave 232 0xE8 -eacute 233 0xE9 -ecircumflex 234 0xEA -ediaeresis 235 0xEB -igrave 236 0xEC -iacute 237 0xED -icircumflex 238 0xEE -idiaeresis 239 0xEF -eth 240 0xF0 -ntilde 241 0xF1 -ograve 242 0xF2 -oacute 243 0xF3 -ocircumflex 244 0xF4 -otilde 245 0xF5 -odiaeresis 246 0xF6 -division 247 0xF7 -oslash 248 0xF8 -ugrave 249 0xF9 -uacute 250 0xFA -ucircumflex 251 0xFB -udiaeresis 252 0xFC -yacute 253 0xFD -thorn 254 0xFE -ydiaeresis 255 0xFF +\(rg (registered) 174 0xAE +\(a- (macron) 175 0xAF +\(de (degree) 176 0xB0 +\(+- (plusminus) 177 0xB1 +\(S2 (twosuperior) 178 0xB2 +\(S3 (threesuperior) 179 0xB3 +\(aa (acute) 180 0xB4 +\(mc (mu) 181 0xB5 +\(ps (paragraph) 182 0xB6 +\(pc (periodcentered) 183 0xB7 +\(ac (cedilla) 184 0xB8 +\(S1 (onesuperior) 185 0xB9 +\(Om (masculine) 186 0xBA +\(Fc (guillemotright) 187 0xBB +\(14 (onequarter) 188 0xBC +\(12 (onehalf) 189 0xBD +\(34 (threequarters) 190 0xBE +\(r? (questiondown) 191 0xBF +\(`A (Agrave) 192 0xC0 +\('A (Aacute) 193 0xC1 +\(^A (Acircumflex) 194 0xC2 +\(~A (Atilde) 195 0xC3 +\(:A (Adiaeresis) 196 0xC4 +\(oA (Aring) 197 0xC5 +\(AE (AE) 198 0xC6 +\(,C (Ccedilla) 199 0xC7 +\(`E (Egrave) 200 0xC8 +\('E (Eacute) 201 0xC9 +\(^E (Ecircumflex) 202 0xCA +\(:E (Ediaeresis) 203 0xCB +\(`I (Igrave) 204 0xCC +\('I (Iacute) 205 0xCD +\(^I (Icircumflex) 206 0xCE +\(:I (Idiaeresis) 207 0xCF +\(-D (ETH) 208 0xD0 +\(~N (Ntilde) 209 0xD1 +\(`O (Ograve) 210 0xD2 +\('O (Oacute) 211 0xD3 +\(^O (Ocircumflex) 212 0xD4 +\(~O (Otilde) 213 0xD5 +\(:O (Odiaeresis) 214 0xD6 +\(mu (multiply) 215 0xD7 +\(/O (Oslash) 216 0xD8 +\(`U (Ugrave) 217 0xD9 +\('U (Uacute) 218 0xDA +\(^U (Ucircumflex) 219 0xDB +\(:U (Udiaeresis) 220 0xDC +\('Y (Yacute) 221 0xDD +\(TP (THORN) 222 0xDE +\(ss (ssharp) 223 0xDF +\(`a (agrave) 224 0xE0 +\('a (aacute) 225 0xE1 +\(^a (acircumflex) 226 0xE2 +\(~a (atilde) 227 0xE3 +\(:a (adiaeresis) 228 0xE4 +\(oa (aring) 229 0xE5 +\(ae (ae) 230 0xE6 +\(,c (ccedilla) 231 0xE7 +\(`e (egrave) 232 0xE8 +\('e (eacute) 233 0xE9 +\(^e (ecircumflex) 234 0xEA +\(:e (ediaeresis) 235 0xEB +\(`i (igrave) 236 0xEC +\('i (iacute) 237 0xED +\(^i (icircumflex) 238 0xEE +\(:i (idiaeresis) 239 0xEF +\(Sd (eth) 240 0xF0 +\(~n (ntilde) 241 0xF1 +\(`o (ograve) 242 0xF2 +\('o (oacute) 243 0xF3 +\(^o (ocircumflex) 244 0xF4 +\(~o (otilde) 245 0xF5 +\(:o (odiaeresis) 246 0xF6 +\(di (division) 247 0xF7 +\(/o (oslash) 248 0xF8 +\(`u (ugrave) 249 0xF9 +\('u (uacute) 250 0xFA +\(^u (ucircumflex) 251 0xFB +\(:u (udiaeresis) 252 0xFC +\('y (yacute) 253 0xFD +\(Tp (thorn) 254 0xFE +\(:y (ydiaeresis) 255 0xFF +.CE +.CS Aogonek 417 0x1A1 breve 418 0x1A2 Lstroke 419 0x1A3 Lcaron 421 0x1A5 Sacute 422 0x1A6 Scaron 425 0x1A9 Scedilla 426 0x1AA Tcaron 427 0x1AB Zacute 428 0x1AC -.CE -.CS Zcaron 430 0x1AE Zabovedot 431 0x1AF aogonek 433 0x1B1 ogonek 434 0x1B2 lstroke 435 0x1B3 @@ -392,10 +392,12 @@ kana_RO 1243 0x4DB kana_WA 1244 0x4DC kana_N 1245 0x4DD voicedsound 1246 0x4DE semivoicedsound 1247 0x4DF +.CE +.CS Arabic_comma 1452 0x5AC Arabic_semicolon 1467 0x5BB Arabic_question_mark 1471 0x5BF Arabic_hamza 1473 0x5C1 Arabic_maddaonalef 1474 0x5C2 @@ -427,12 +429,10 @@ Arabic_feh 1505 0x5E1 Arabic_qaf 1506 0x5E2 Arabic_kaf 1507 0x5E3 Arabic_lam 1508 0x5E4 Arabic_meem 1509 0x5E5 -.CE -.CS Arabic_noon 1510 0x5E6 Arabic_ha 1511 0x5E7 Arabic_waw 1512 0x5E8 Arabic_alefmaksura 1513 0x5E9 Arabic_yeh 1514 0x5EA @@ -542,13 +542,15 @@ Greek_ALPHAaccent 1953 0x7A1 Greek_EPSILONaccent 1954 0x7A2 Greek_ETAaccent 1955 0x7A3 Greek_IOTAaccent 1956 0x7A4 Greek_IOTAdieresis 1957 0x7A5 +Greek_IOTAaccentdiaeresis 1958 0x7A6 Greek_OMICRONaccent 1959 0x7A7 Greek_UPSILONaccent 1960 0x7A8 Greek_UPSILONdieresis 1961 0x7A9 +Greek_UPSILONaccentdieresis 1962 0x7AA Greek_OMEGAaccent 1963 0x7AB Greek_accentdieresis 1966 0x7AE Greek_horizbar 1967 0x7AF Greek_alphaaccent 1969 0x7B1 Greek_epsilonaccent 1970 0x7B2 @@ -608,10 +610,12 @@ Greek_upsilon 2037 0x7F5 Greek_phi 2038 0x7F6 Greek_chi 2039 0x7F7 Greek_psi 2040 0x7F8 Greek_omega 2041 0x7F9 +.CE +.CS leftradical 2209 0x8A1 topleftradical 2210 0x8A2 horizconnector 2211 0x8A3 topintegral 2212 0x8A4 botintegral 2213 0x8A5 @@ -631,12 +635,10 @@ topvertsummationconnector 2227 0x8B3 botvertsummationconnector 2228 0x8B4 toprightsummation 2229 0x8B5 botrightsummation 2230 0x8B6 rightmiddlesummation 2231 0x8B7 -.CE -.CS lessthanequal 2236 0x8BC notequal 2237 0x8BD greaterthanequal 2238 0x8BE integral 2239 0x8BF therefore 2240 0x8C0 @@ -814,10 +816,12 @@ hebrew_zade 3318 0xCF6 hebrew_qoph 3319 0xCF7 hebrew_resh 3320 0xCF8 hebrew_shin 3321 0xCF9 hebrew_taw 3322 0xCFA +.CE +.CS Thai_kokai 3489 0xDA1 Thai_khokhai 3490 0xDA2 Thai_khokhuat 3491 0xDA3 Thai_khokhwai 3492 0xDA4 Thai_khokhon 3493 0xDA5 @@ -992,11 +996,13 @@ Hangul_J_YeorinHieuh 3834 0xEFA Korean_Won 3839 0xEFF OE 5052 0x13BC oe 5053 0x13BD Ydiaeresis 5054 0x13BE -EuroSign 8364 0x20AC +\(eu (EuroSign) 8364 0x20AC +.CE +.CS 3270_Duplicate 64769 0xFD01 3270_FieldMark 64770 0xFD02 3270_Right2 64771 0xFD03 3270_Left2 64772 0xFD04 3270_BackTab 64773 0xFD05 @@ -1163,10 +1169,12 @@ Pointer_EnableKeys 65273 0xFEF9 Pointer_Accelerate 65274 0xFEFA Pointer_DfltBtnNext 65275 0xFEFB Pointer_DfltBtnPrev 65276 0xFEFC Pointer_Drag5 65277 0xFEFD +.CE +.CS BackSpace 65288 0xFF08 Tab 65289 0xFF09 Linefeed 65290 0xFF0A Clear 65291 0xFF0B Return 65293 0xFF0D @@ -1213,22 +1221,17 @@ Down 65364 0xFF54 Prior 65365 0xFF55 Next 65366 0xFF56 End 65367 0xFF57 Begin 65368 0xFF58 -Win_L 65371 0xFF5B -Win_R 65372 0xFF5C -.CE -.CS -App 65373 0xFF5D Select 65376 0xFF60 Print 65377 0xFF61 Execute 65378 0xFF62 Insert 65379 0xFF63 Undo 65381 0xFF65 Redo 65382 0xFF66 -Menu 65383 0xFF67 +Menu (App) 65383 0xFF67 Find 65384 0xFF68 Cancel 65385 0xFF69 Help 65386 0xFF6A Break 65387 0xFF6B Mode_switch 65406 0xFF7E @@ -1311,12 +1314,12 @@ Shift_Lock 65510 0xFFE6 Meta_L 65511 0xFFE7 Meta_R 65512 0xFFE8 Alt_L 65513 0xFFE9 Alt_R 65514 0xFFEA -Super_L 65515 0xFFEB -Super_R 65516 0xFFEC +Super_L (Win_L) 65515 0xFFEB +Super_R (Win_R) 65516 0xFFEC Hyper_L 65517 0xFFED Hyper_R 65518 0xFFEE braille_dot_1 65521 0xFFF1 braille_dot_2 65522 0xFFF2 braille_dot_3 65523 0xFFF3 @@ -1326,719 +1329,12 @@ braille_dot_7 65527 0xFFF7 braille_dot_8 65528 0xFFF8 braille_dot_9 65529 0xFFF9 braille_dot_10 65530 0xFFFA Delete 65535 0xFFFF -Ibreve 16777516 0x100012C -ibreve 16777517 0x100012D -Wcircumflex 16777588 0x1000174 -wcircumflex 16777589 0x1000175 -Ycircumflex 16777590 0x1000176 -ycircumflex 16777591 0x1000177 -SCHWA 16777615 0x100018F -Obarred 16777631 0x100019F -Ohorn 16777632 0x10001A0 -ohorn 16777633 0x10001A1 -Uhorn 16777647 0x10001AF -uhorn 16777648 0x10001B0 -Zstroke 16777653 0x10001B5 -zstroke 16777654 0x10001B6 -EZH 16777655 0x10001B7 -Ocaron 16777681 0x10001D1 -ocaron 16777682 0x10001D2 -Gcaron 16777702 0x10001E6 -gcaron 16777703 0x10001E7 -schwa 16777817 0x1000259 -obarred 16777845 0x1000275 -ezh 16777874 0x1000292 -Cyrillic_GHE_bar 16778386 0x1000492 -Cyrillic_ghe_bar 16778387 0x1000493 -Cyrillic_ZHE_descender 16778390 0x1000496 -Cyrillic_zhe_descender 16778391 0x1000497 -Cyrillic_KA_descender 16778394 0x100049A -Cyrillic_ka_descender 16778395 0x100049B -Cyrillic_KA_vertstroke 16778396 0x100049C -Cyrillic_ka_vertstroke 16778397 0x100049D -Cyrillic_EN_descender 16778402 0x10004A2 -Cyrillic_en_descender 16778403 0x10004A3 -Cyrillic_U_straight 16778414 0x10004AE -Cyrillic_u_straight 16778415 0x10004AF -Cyrillic_U_straight_bar 16778416 0x10004B0 -Cyrillic_u_straight_bar 16778417 0x10004B1 -Cyrillic_HA_descender 16778418 0x10004B2 -Cyrillic_ha_descender 16778419 0x10004B3 -Cyrillic_CHE_descender 16778422 0x10004B6 -Cyrillic_che_descender 16778423 0x10004B7 -Cyrillic_CHE_vertstroke 16778424 0x10004B8 -Cyrillic_che_vertstroke 16778425 0x10004B9 -Cyrillic_SHHA 16778426 0x10004BA -Cyrillic_shha 16778427 0x10004BB -Cyrillic_SCHWA 16778456 0x10004D8 -Cyrillic_schwa 16778457 0x10004D9 -Cyrillic_I_macron 16778466 0x10004E2 -Cyrillic_i_macron 16778467 0x10004E3 -Cyrillic_O_bar 16778472 0x10004E8 -Cyrillic_o_bar 16778473 0x10004E9 -Cyrillic_U_macron 16778478 0x10004EE -Cyrillic_u_macron 16778479 0x10004EF -Armenian_AYB 16778545 0x1000531 -Armenian_BEN 16778546 0x1000532 -Armenian_GIM 16778547 0x1000533 -Armenian_DA 16778548 0x1000534 -Armenian_YECH 16778549 0x1000535 -Armenian_ZA 16778550 0x1000536 -Armenian_E 16778551 0x1000537 -Armenian_AT 16778552 0x1000538 -Armenian_TO 16778553 0x1000539 -Armenian_ZHE 16778554 0x100053A -Armenian_INI 16778555 0x100053B -Armenian_LYUN 16778556 0x100053C -Armenian_KHE 16778557 0x100053D -Armenian_TSA 16778558 0x100053E -Armenian_KEN 16778559 0x100053F -Armenian_HO 16778560 0x1000540 -Armenian_DZA 16778561 0x1000541 -Armenian_GHAT 16778562 0x1000542 -Armenian_TCHE 16778563 0x1000543 -Armenian_MEN 16778564 0x1000544 -Armenian_HI 16778565 0x1000545 -Armenian_NU 16778566 0x1000546 -Armenian_SHA 16778567 0x1000547 -Armenian_VO 16778568 0x1000548 -Armenian_CHA 16778569 0x1000549 -Armenian_PE 16778570 0x100054A -Armenian_JE 16778571 0x100054B -Armenian_RA 16778572 0x100054C -Armenian_SE 16778573 0x100054D -Armenian_VEV 16778574 0x100054E -Armenian_TYUN 16778575 0x100054F -Armenian_RE 16778576 0x1000550 -Armenian_TSO 16778577 0x1000551 -Armenian_VYUN 16778578 0x1000552 -Armenian_PYUR 16778579 0x1000553 -Armenian_KE 16778580 0x1000554 -Armenian_O 16778581 0x1000555 -Armenian_FE 16778582 0x1000556 -Armenian_apostrophe 16778586 0x100055A -Armenian_accent 16778587 0x100055B -Armenian_exclam 16778588 0x100055C -Armenian_separation_mark 16778589 0x100055D -Armenian_question 16778590 0x100055E -Armenian_ayb 16778593 0x1000561 -Armenian_ben 16778594 0x1000562 -Armenian_gim 16778595 0x1000563 -Armenian_da 16778596 0x1000564 -Armenian_yech 16778597 0x1000565 -Armenian_za 16778598 0x1000566 -Armenian_e 16778599 0x1000567 -Armenian_at 16778600 0x1000568 -Armenian_to 16778601 0x1000569 -Armenian_zhe 16778602 0x100056A -Armenian_ini 16778603 0x100056B -Armenian_lyun 16778604 0x100056C -Armenian_khe 16778605 0x100056D -Armenian_tsa 16778606 0x100056E -Armenian_ken 16778607 0x100056F -Armenian_ho 16778608 0x1000570 -Armenian_dza 16778609 0x1000571 -Armenian_ghat 16778610 0x1000572 -Armenian_tche 16778611 0x1000573 -Armenian_men 16778612 0x1000574 -Armenian_hi 16778613 0x1000575 -Armenian_nu 16778614 0x1000576 -Armenian_sha 16778615 0x1000577 -Armenian_vo 16778616 0x1000578 -Armenian_cha 16778617 0x1000579 -Armenian_pe 16778618 0x100057A -Armenian_je 16778619 0x100057B -Armenian_ra 16778620 0x100057C -Armenian_se 16778621 0x100057D -Armenian_vev 16778622 0x100057E -Armenian_tyun 16778623 0x100057F -Armenian_re 16778624 0x1000580 -Armenian_tso 16778625 0x1000581 -Armenian_vyun 16778626 0x1000582 -Armenian_pyur 16778627 0x1000583 -Armenian_ke 16778628 0x1000584 -Armenian_o 16778629 0x1000585 -Armenian_fe 16778630 0x1000586 -Armenian_ligature_ew 16778631 0x1000587 -Armenian_full_stop 16778633 0x1000589 -Armenian_hyphen 16778634 0x100058A -Arabic_madda_above 16778835 0x1000653 -Arabic_hamza_above 16778836 0x1000654 -Arabic_hamza_below 16778837 0x1000655 -Arabic_0 16778848 0x1000660 -Arabic_1 16778849 0x1000661 -Arabic_2 16778850 0x1000662 -Arabic_3 16778851 0x1000663 -Arabic_4 16778852 0x1000664 -Arabic_5 16778853 0x1000665 -Arabic_6 16778854 0x1000666 -Arabic_7 16778855 0x1000667 -Arabic_8 16778856 0x1000668 -Arabic_9 16778857 0x1000669 -Arabic_percent 16778858 0x100066A -Arabic_superscript_alef 16778864 0x1000670 -Arabic_tteh 16778873 0x1000679 -Arabic_peh 16778878 0x100067E -Arabic_tcheh 16778886 0x1000686 -Arabic_ddal 16778888 0x1000688 -Arabic_rreh 16778897 0x1000691 -Arabic_jeh 16778904 0x1000698 -Arabic_veh 16778916 0x10006A4 -Arabic_keheh 16778921 0x10006A9 -Arabic_gaf 16778927 0x10006AF -Arabic_noon_ghunna 16778938 0x10006BA -Arabic_heh_doachashmee 16778942 0x10006BE -Arabic_heh_goal 16778945 0x10006C1 -Farsi_yeh 16778956 0x10006CC -Arabic_yeh_baree 16778962 0x10006D2 -Arabic_fullstop 16778964 0x10006D4 -Farsi_0 16778992 0x10006F0 -Farsi_1 16778993 0x10006F1 -Farsi_2 16778994 0x10006F2 -Farsi_3 16778995 0x10006F3 -Farsi_4 16778996 0x10006F4 -Farsi_5 16778997 0x10006F5 -Farsi_6 16778998 0x10006F6 -Farsi_7 16778999 0x10006F7 -Farsi_8 16779000 0x10006F8 -Farsi_9 16779001 0x10006F9 -Sinh_ng 16780674 0x1000D82 -Sinh_h2 16780675 0x1000D83 -Sinh_a 16780677 0x1000D85 -Sinh_aa 16780678 0x1000D86 -Sinh_ae 16780679 0x1000D87 -Sinh_aee 16780680 0x1000D88 -Sinh_i 16780681 0x1000D89 -Sinh_ii 16780682 0x1000D8A -Sinh_u 16780683 0x1000D8B -Sinh_uu 16780684 0x1000D8C -Sinh_ri 16780685 0x1000D8D -Sinh_rii 16780686 0x1000D8E -Sinh_lu 16780687 0x1000D8F -Sinh_luu 16780688 0x1000D90 -Sinh_e 16780689 0x1000D91 -Sinh_ee 16780690 0x1000D92 -Sinh_ai 16780691 0x1000D93 -Sinh_o 16780692 0x1000D94 -Sinh_oo 16780693 0x1000D95 -Sinh_au 16780694 0x1000D96 -Sinh_ka 16780698 0x1000D9A -Sinh_kha 16780699 0x1000D9B -Sinh_ga 16780700 0x1000D9C -Sinh_gha 16780701 0x1000D9D -Sinh_ng2 16780702 0x1000D9E -Sinh_nga 16780703 0x1000D9F -Sinh_ca 16780704 0x1000DA0 -Sinh_cha 16780705 0x1000DA1 -Sinh_ja 16780706 0x1000DA2 -Sinh_jha 16780707 0x1000DA3 -Sinh_nya 16780708 0x1000DA4 -Sinh_jnya 16780709 0x1000DA5 -Sinh_nja 16780710 0x1000DA6 -Sinh_tta 16780711 0x1000DA7 -Sinh_ttha 16780712 0x1000DA8 -Sinh_dda 16780713 0x1000DA9 -Sinh_ddha 16780714 0x1000DAA -Sinh_nna 16780715 0x1000DAB -Sinh_ndda 16780716 0x1000DAC -Sinh_tha 16780717 0x1000DAD -Sinh_thha 16780718 0x1000DAE -Sinh_dha 16780719 0x1000DAF -Sinh_dhha 16780720 0x1000DB0 -Sinh_na 16780721 0x1000DB1 -Sinh_ndha 16780723 0x1000DB3 -Sinh_pa 16780724 0x1000DB4 -Sinh_pha 16780725 0x1000DB5 -Sinh_ba 16780726 0x1000DB6 -Sinh_bha 16780727 0x1000DB7 -Sinh_ma 16780728 0x1000DB8 -Sinh_mba 16780729 0x1000DB9 -Sinh_ya 16780730 0x1000DBA -Sinh_ra 16780731 0x1000DBB -Sinh_la 16780733 0x1000DBD -Sinh_va 16780736 0x1000DC0 -Sinh_sha 16780737 0x1000DC1 -Sinh_ssha 16780738 0x1000DC2 -Sinh_sa 16780739 0x1000DC3 -Sinh_ha 16780740 0x1000DC4 -Sinh_lla 16780741 0x1000DC5 -Sinh_fa 16780742 0x1000DC6 -Sinh_al 16780746 0x1000DCA -Sinh_aa2 16780751 0x1000DCF -Sinh_ae2 16780752 0x1000DD0 -Sinh_aee2 16780753 0x1000DD1 -Sinh_i2 16780754 0x1000DD2 -Sinh_ii2 16780755 0x1000DD3 -Sinh_u2 16780756 0x1000DD4 -Sinh_uu2 16780758 0x1000DD6 -Sinh_ru2 16780760 0x1000DD8 -Sinh_e2 16780761 0x1000DD9 -Sinh_ee2 16780762 0x1000DDA -Sinh_ai2 16780763 0x1000DDB -Sinh_o2 16780764 0x1000DDC -Sinh_oo2 16780765 0x1000DDD -Sinh_au2 16780766 0x1000DDE -Sinh_lu2 16780767 0x1000DDF -Sinh_ruu2 16780786 0x1000DF2 -Sinh_luu2 16780787 0x1000DF3 -Sinh_kunddaliya 16780788 0x1000DF4 -Georgian_an 16781520 0x10010D0 -Georgian_ban 16781521 0x10010D1 -Georgian_gan 16781522 0x10010D2 -Georgian_don 16781523 0x10010D3 -Georgian_en 16781524 0x10010D4 -Georgian_vin 16781525 0x10010D5 -Georgian_zen 16781526 0x10010D6 -Georgian_tan 16781527 0x10010D7 -Georgian_in 16781528 0x10010D8 -Georgian_kan 16781529 0x10010D9 -Georgian_las 16781530 0x10010DA -Georgian_man 16781531 0x10010DB -Georgian_nar 16781532 0x10010DC -Georgian_on 16781533 0x10010DD -Georgian_par 16781534 0x10010DE -Georgian_zhar 16781535 0x10010DF -Georgian_rae 16781536 0x10010E0 -Georgian_san 16781537 0x10010E1 -Georgian_tar 16781538 0x10010E2 -Georgian_un 16781539 0x10010E3 -Georgian_phar 16781540 0x10010E4 -Georgian_khar 16781541 0x10010E5 -Georgian_ghan 16781542 0x10010E6 -Georgian_qar 16781543 0x10010E7 -Georgian_shin 16781544 0x10010E8 -Georgian_chin 16781545 0x10010E9 -Georgian_can 16781546 0x10010EA -Georgian_jil 16781547 0x10010EB -Georgian_cil 16781548 0x10010EC -Georgian_char 16781549 0x10010ED -Georgian_xan 16781550 0x10010EE -Georgian_jhan 16781551 0x10010EF -Georgian_hae 16781552 0x10010F0 -Georgian_he 16781553 0x10010F1 -Georgian_hie 16781554 0x10010F2 -Georgian_we 16781555 0x10010F3 -Georgian_har 16781556 0x10010F4 -Georgian_hoe 16781557 0x10010F5 -Georgian_fi 16781558 0x10010F6 -Babovedot 16784898 0x1001E02 -babovedot 16784899 0x1001E03 -Dabovedot 16784906 0x1001E0A -dabovedot 16784907 0x1001E0B -Fabovedot 16784926 0x1001E1E -fabovedot 16784927 0x1001E1F -Lbelowdot 16784950 0x1001E36 -lbelowdot 16784951 0x1001E37 -Mabovedot 16784960 0x1001E40 -mabovedot 16784961 0x1001E41 -Pabovedot 16784982 0x1001E56 -pabovedot 16784983 0x1001E57 -Sabovedot 16784992 0x1001E60 -sabovedot 16784993 0x1001E61 -Tabovedot 16785002 0x1001E6A -tabovedot 16785003 0x1001E6B -Wgrave 16785024 0x1001E80 -wgrave 16785025 0x1001E81 -Wacute 16785026 0x1001E82 -wacute 16785027 0x1001E83 -Wdiaeresis 16785028 0x1001E84 -wdiaeresis 16785029 0x1001E85 -Xabovedot 16785034 0x1001E8A -xabovedot 16785035 0x1001E8B -Abelowdot 16785056 0x1001EA0 -abelowdot 16785057 0x1001EA1 -Ahook 16785058 0x1001EA2 -ahook 16785059 0x1001EA3 -Acircumflexacute 16785060 0x1001EA4 -acircumflexacute 16785061 0x1001EA5 -Acircumflexgrave 16785062 0x1001EA6 -acircumflexgrave 16785063 0x1001EA7 -Acircumflexhook 16785064 0x1001EA8 -acircumflexhook 16785065 0x1001EA9 -Acircumflextilde 16785066 0x1001EAA -acircumflextilde 16785067 0x1001EAB -Acircumflexbelowdot 16785068 0x1001EAC -acircumflexbelowdot 16785069 0x1001EAD -Abreveacute 16785070 0x1001EAE -abreveacute 16785071 0x1001EAF -Abrevegrave 16785072 0x1001EB0 -abrevegrave 16785073 0x1001EB1 -Abrevehook 16785074 0x1001EB2 -abrevehook 16785075 0x1001EB3 -Abrevetilde 16785076 0x1001EB4 -abrevetilde 16785077 0x1001EB5 -Abrevebelowdot 16785078 0x1001EB6 -abrevebelowdot 16785079 0x1001EB7 -Ebelowdot 16785080 0x1001EB8 -ebelowdot 16785081 0x1001EB9 -Ehook 16785082 0x1001EBA -ehook 16785083 0x1001EBB -Etilde 16785084 0x1001EBC -etilde 16785085 0x1001EBD -Ecircumflexacute 16785086 0x1001EBE -ecircumflexacute 16785087 0x1001EBF -Ecircumflexgrave 16785088 0x1001EC0 -ecircumflexgrave 16785089 0x1001EC1 -Ecircumflexhook 16785090 0x1001EC2 -ecircumflexhook 16785091 0x1001EC3 -Ecircumflextilde 16785092 0x1001EC4 -ecircumflextilde 16785093 0x1001EC5 -Ecircumflexbelowdot 16785094 0x1001EC6 -ecircumflexbelowdot 16785095 0x1001EC7 -Ihook 16785096 0x1001EC8 -ihook 16785097 0x1001EC9 -Ibelowdot 16785098 0x1001ECA -ibelowdot 16785099 0x1001ECB -Obelowdot 16785100 0x1001ECC -obelowdot 16785101 0x1001ECD -Ohook 16785102 0x1001ECE -ohook 16785103 0x1001ECF -Ocircumflexacute 16785104 0x1001ED0 -ocircumflexacute 16785105 0x1001ED1 -Ocircumflexgrave 16785106 0x1001ED2 -ocircumflexgrave 16785107 0x1001ED3 -Ocircumflexhook 16785108 0x1001ED4 -ocircumflexhook 16785109 0x1001ED5 -Ocircumflextilde 16785110 0x1001ED6 -ocircumflextilde 16785111 0x1001ED7 -Ocircumflexbelowdot 16785112 0x1001ED8 -ocircumflexbelowdot 16785113 0x1001ED9 -Ohornacute 16785114 0x1001EDA -ohornacute 16785115 0x1001EDB -Ohorngrave 16785116 0x1001EDC -ohorngrave 16785117 0x1001EDD -Ohornhook 16785118 0x1001EDE -ohornhook 16785119 0x1001EDF -Ohorntilde 16785120 0x1001EE0 -ohorntilde 16785121 0x1001EE1 -Ohornbelowdot 16785122 0x1001EE2 -ohornbelowdot 16785123 0x1001EE3 -Ubelowdot 16785124 0x1001EE4 -ubelowdot 16785125 0x1001EE5 -Uhook 16785126 0x1001EE6 -uhook 16785127 0x1001EE7 -Uhornacute 16785128 0x1001EE8 -uhornacute 16785129 0x1001EE9 -Uhorngrave 16785130 0x1001EEA -uhorngrave 16785131 0x1001EEB -Uhornhook 16785132 0x1001EEC -uhornhook 16785133 0x1001EED -Uhorntilde 16785134 0x1001EEE -uhorntilde 16785135 0x1001EEF -Uhornbelowdot 16785136 0x1001EF0 -uhornbelowdot 16785137 0x1001EF1 -Ygrave 16785138 0x1001EF2 -ygrave 16785139 0x1001EF3 -Ybelowdot 16785140 0x1001EF4 -ybelowdot 16785141 0x1001EF5 -Yhook 16785142 0x1001EF6 -yhook 16785143 0x1001EF7 -Ytilde 16785144 0x1001EF8 -ytilde 16785145 0x1001EF9 -zerosuperior 16785520 0x1002070 -foursuperior 16785524 0x1002074 -fivesuperior 16785525 0x1002075 -sixsuperior 16785526 0x1002076 -sevensuperior 16785527 0x1002077 -eightsuperior 16785528 0x1002078 -ninesuperior 16785529 0x1002079 -zerosubscript 16785536 0x1002080 -onesubscript 16785537 0x1002081 -twosubscript 16785538 0x1002082 -threesubscript 16785539 0x1002083 -foursubscript 16785540 0x1002084 -fivesubscript 16785541 0x1002085 -sixsubscript 16785542 0x1002086 -sevensubscript 16785543 0x1002087 -eightsubscript 16785544 0x1002088 -ninesubscript 16785545 0x1002089 -EcuSign 16785568 0x10020A0 -ColonSign 16785569 0x10020A1 -CruzeiroSign 16785570 0x10020A2 -FFrancSign 16785571 0x10020A3 -LiraSign 16785572 0x10020A4 -MillSign 16785573 0x10020A5 -NairaSign 16785574 0x10020A6 -PesetaSign 16785575 0x10020A7 -RupeeSign 16785576 0x10020A8 -WonSign 16785577 0x10020A9 -NewSheqelSign 16785578 0x10020AA -DongSign 16785579 0x10020AB -partdifferential 16785922 0x1002202 -emptyset 16785925 0x1002205 -elementof 16785928 0x1002208 -notelementof 16785929 0x1002209 -containsas 16785931 0x100220B -squareroot 16785946 0x100221A -cuberoot 16785947 0x100221B -fourthroot 16785948 0x100221C -dintegral 16785964 0x100222C -tintegral 16785965 0x100222D -because 16785973 0x1002235 -notapproxeq 16785991 0x1002247 -approxeq 16785992 0x1002248 -notidentical 16786018 0x1002262 -stricteq 16786019 0x1002263 -braille_blank 16787456 0x1002800 -braille_dots_1 16787457 0x1002801 -braille_dots_2 16787458 0x1002802 -braille_dots_12 16787459 0x1002803 -braille_dots_3 16787460 0x1002804 -braille_dots_13 16787461 0x1002805 -braille_dots_23 16787462 0x1002806 -braille_dots_123 16787463 0x1002807 -braille_dots_4 16787464 0x1002808 -braille_dots_14 16787465 0x1002809 -braille_dots_24 16787466 0x100280A -braille_dots_124 16787467 0x100280B -braille_dots_34 16787468 0x100280C -braille_dots_134 16787469 0x100280D -braille_dots_234 16787470 0x100280E -braille_dots_1234 16787471 0x100280F -braille_dots_5 16787472 0x1002810 -braille_dots_15 16787473 0x1002811 -braille_dots_25 16787474 0x1002812 -braille_dots_125 16787475 0x1002813 -braille_dots_35 16787476 0x1002814 -braille_dots_135 16787477 0x1002815 -braille_dots_235 16787478 0x1002816 -braille_dots_1235 16787479 0x1002817 -braille_dots_45 16787480 0x1002818 -braille_dots_145 16787481 0x1002819 -braille_dots_245 16787482 0x100281A -braille_dots_1245 16787483 0x100281B -braille_dots_345 16787484 0x100281C -braille_dots_1345 16787485 0x100281D -braille_dots_2345 16787486 0x100281E -braille_dots_12345 16787487 0x100281F -braille_dots_6 16787488 0x1002820 -braille_dots_16 16787489 0x1002821 -braille_dots_26 16787490 0x1002822 -braille_dots_126 16787491 0x1002823 -braille_dots_36 16787492 0x1002824 -braille_dots_136 16787493 0x1002825 -braille_dots_236 16787494 0x1002826 -braille_dots_1236 16787495 0x1002827 -braille_dots_46 16787496 0x1002828 -braille_dots_146 16787497 0x1002829 -braille_dots_246 16787498 0x100282A -braille_dots_1246 16787499 0x100282B -braille_dots_346 16787500 0x100282C -braille_dots_1346 16787501 0x100282D -braille_dots_2346 16787502 0x100282E -braille_dots_12346 16787503 0x100282F -braille_dots_56 16787504 0x1002830 -braille_dots_156 16787505 0x1002831 -braille_dots_256 16787506 0x1002832 -braille_dots_1256 16787507 0x1002833 -braille_dots_356 16787508 0x1002834 -braille_dots_1356 16787509 0x1002835 -braille_dots_2356 16787510 0x1002836 -braille_dots_12356 16787511 0x1002837 -braille_dots_456 16787512 0x1002838 -braille_dots_1456 16787513 0x1002839 -braille_dots_2456 16787514 0x100283A -braille_dots_12456 16787515 0x100283B -braille_dots_3456 16787516 0x100283C -braille_dots_13456 16787517 0x100283D -braille_dots_23456 16787518 0x100283E -braille_dots_123456 16787519 0x100283F -braille_dots_7 16787520 0x1002840 -braille_dots_17 16787521 0x1002841 -braille_dots_27 16787522 0x1002842 -braille_dots_127 16787523 0x1002843 -braille_dots_37 16787524 0x1002844 -braille_dots_137 16787525 0x1002845 -braille_dots_237 16787526 0x1002846 -braille_dots_1237 16787527 0x1002847 -braille_dots_47 16787528 0x1002848 -braille_dots_147 16787529 0x1002849 -braille_dots_247 16787530 0x100284A -braille_dots_1247 16787531 0x100284B -braille_dots_347 16787532 0x100284C -braille_dots_1347 16787533 0x100284D -braille_dots_2347 16787534 0x100284E -braille_dots_12347 16787535 0x100284F -braille_dots_57 16787536 0x1002850 -braille_dots_157 16787537 0x1002851 -braille_dots_257 16787538 0x1002852 -braille_dots_1257 16787539 0x1002853 -braille_dots_357 16787540 0x1002854 -braille_dots_1357 16787541 0x1002855 -braille_dots_2357 16787542 0x1002856 -braille_dots_12357 16787543 0x1002857 -braille_dots_457 16787544 0x1002858 -braille_dots_1457 16787545 0x1002859 -braille_dots_2457 16787546 0x100285A -braille_dots_12457 16787547 0x100285B -braille_dots_3457 16787548 0x100285C -braille_dots_13457 16787549 0x100285D -braille_dots_23457 16787550 0x100285E -braille_dots_123457 16787551 0x100285F -braille_dots_67 16787552 0x1002860 -braille_dots_167 16787553 0x1002861 -braille_dots_267 16787554 0x1002862 -braille_dots_1267 16787555 0x1002863 -braille_dots_367 16787556 0x1002864 -braille_dots_1367 16787557 0x1002865 -braille_dots_2367 16787558 0x1002866 -braille_dots_12367 16787559 0x1002867 -braille_dots_467 16787560 0x1002868 -braille_dots_1467 16787561 0x1002869 -braille_dots_2467 16787562 0x100286A -braille_dots_12467 16787563 0x100286B -braille_dots_3467 16787564 0x100286C -braille_dots_13467 16787565 0x100286D -braille_dots_23467 16787566 0x100286E -braille_dots_123467 16787567 0x100286F -braille_dots_567 16787568 0x1002870 -braille_dots_1567 16787569 0x1002871 -braille_dots_2567 16787570 0x1002872 -braille_dots_12567 16787571 0x1002873 -braille_dots_3567 16787572 0x1002874 -braille_dots_13567 16787573 0x1002875 -braille_dots_23567 16787574 0x1002876 -braille_dots_123567 16787575 0x1002877 -braille_dots_4567 16787576 0x1002878 -braille_dots_14567 16787577 0x1002879 -braille_dots_24567 16787578 0x100287A -braille_dots_124567 16787579 0x100287B -braille_dots_34567 16787580 0x100287C -braille_dots_134567 16787581 0x100287D -braille_dots_234567 16787582 0x100287E -braille_dots_1234567 16787583 0x100287F -braille_dots_8 16787584 0x1002880 -braille_dots_18 16787585 0x1002881 -braille_dots_28 16787586 0x1002882 -braille_dots_128 16787587 0x1002883 -braille_dots_38 16787588 0x1002884 -braille_dots_138 16787589 0x1002885 -braille_dots_238 16787590 0x1002886 -braille_dots_1238 16787591 0x1002887 -braille_dots_48 16787592 0x1002888 -braille_dots_148 16787593 0x1002889 -braille_dots_248 16787594 0x100288A -braille_dots_1248 16787595 0x100288B -braille_dots_348 16787596 0x100288C -braille_dots_1348 16787597 0x100288D -braille_dots_2348 16787598 0x100288E -braille_dots_12348 16787599 0x100288F -braille_dots_58 16787600 0x1002890 -braille_dots_158 16787601 0x1002891 -braille_dots_258 16787602 0x1002892 -braille_dots_1258 16787603 0x1002893 -braille_dots_358 16787604 0x1002894 -braille_dots_1358 16787605 0x1002895 -braille_dots_2358 16787606 0x1002896 -braille_dots_12358 16787607 0x1002897 -braille_dots_458 16787608 0x1002898 -braille_dots_1458 16787609 0x1002899 -braille_dots_2458 16787610 0x100289A -braille_dots_12458 16787611 0x100289B -braille_dots_3458 16787612 0x100289C -braille_dots_13458 16787613 0x100289D -braille_dots_23458 16787614 0x100289E -braille_dots_123458 16787615 0x100289F -braille_dots_68 16787616 0x10028A0 -braille_dots_168 16787617 0x10028A1 -braille_dots_268 16787618 0x10028A2 -braille_dots_1268 16787619 0x10028A3 -braille_dots_368 16787620 0x10028A4 -braille_dots_1368 16787621 0x10028A5 -braille_dots_2368 16787622 0x10028A6 -braille_dots_12368 16787623 0x10028A7 -braille_dots_468 16787624 0x10028A8 -braille_dots_1468 16787625 0x10028A9 -braille_dots_2468 16787626 0x10028AA -braille_dots_12468 16787627 0x10028AB -braille_dots_3468 16787628 0x10028AC -braille_dots_13468 16787629 0x10028AD -braille_dots_23468 16787630 0x10028AE -braille_dots_123468 16787631 0x10028AF -braille_dots_568 16787632 0x10028B0 -braille_dots_1568 16787633 0x10028B1 -braille_dots_2568 16787634 0x10028B2 -braille_dots_12568 16787635 0x10028B3 -braille_dots_3568 16787636 0x10028B4 -braille_dots_13568 16787637 0x10028B5 -braille_dots_23568 16787638 0x10028B6 -braille_dots_123568 16787639 0x10028B7 -braille_dots_4568 16787640 0x10028B8 -braille_dots_14568 16787641 0x10028B9 -braille_dots_24568 16787642 0x10028BA -braille_dots_124568 16787643 0x10028BB -braille_dots_34568 16787644 0x10028BC -braille_dots_134568 16787645 0x10028BD -braille_dots_234568 16787646 0x10028BE -braille_dots_1234568 16787647 0x10028BF -braille_dots_78 16787648 0x10028C0 -braille_dots_178 16787649 0x10028C1 -braille_dots_278 16787650 0x10028C2 -braille_dots_1278 16787651 0x10028C3 -braille_dots_378 16787652 0x10028C4 -braille_dots_1378 16787653 0x10028C5 -braille_dots_2378 16787654 0x10028C6 -braille_dots_12378 16787655 0x10028C7 -braille_dots_478 16787656 0x10028C8 -braille_dots_1478 16787657 0x10028C9 -braille_dots_2478 16787658 0x10028CA -braille_dots_12478 16787659 0x10028CB -braille_dots_3478 16787660 0x10028CC -braille_dots_13478 16787661 0x10028CD -braille_dots_23478 16787662 0x10028CE -braille_dots_123478 16787663 0x10028CF -braille_dots_578 16787664 0x10028D0 -braille_dots_1578 16787665 0x10028D1 -braille_dots_2578 16787666 0x10028D2 -braille_dots_12578 16787667 0x10028D3 -braille_dots_3578 16787668 0x10028D4 -braille_dots_13578 16787669 0x10028D5 -braille_dots_23578 16787670 0x10028D6 -braille_dots_123578 16787671 0x10028D7 -braille_dots_4578 16787672 0x10028D8 -braille_dots_14578 16787673 0x10028D9 -braille_dots_24578 16787674 0x10028DA -braille_dots_124578 16787675 0x10028DB -braille_dots_34578 16787676 0x10028DC -braille_dots_134578 16787677 0x10028DD -braille_dots_234578 16787678 0x10028DE -braille_dots_1234578 16787679 0x10028DF -braille_dots_678 16787680 0x10028E0 -braille_dots_1678 16787681 0x10028E1 -braille_dots_2678 16787682 0x10028E2 -braille_dots_12678 16787683 0x10028E3 -braille_dots_3678 16787684 0x10028E4 -braille_dots_13678 16787685 0x10028E5 -braille_dots_23678 16787686 0x10028E6 -braille_dots_123678 16787687 0x10028E7 -braille_dots_4678 16787688 0x10028E8 -braille_dots_14678 16787689 0x10028E9 -braille_dots_24678 16787690 0x10028EA -braille_dots_124678 16787691 0x10028EB -braille_dots_34678 16787692 0x10028EC -braille_dots_134678 16787693 0x10028ED -braille_dots_234678 16787694 0x10028EE -braille_dots_1234678 16787695 0x10028EF -braille_dots_5678 16787696 0x10028F0 -braille_dots_15678 16787697 0x10028F1 -braille_dots_25678 16787698 0x10028F2 -braille_dots_125678 16787699 0x10028F3 -braille_dots_35678 16787700 0x10028F4 -braille_dots_135678 16787701 0x10028F5 -braille_dots_235678 16787702 0x10028F6 -braille_dots_1235678 16787703 0x10028F7 -braille_dots_45678 16787704 0x10028F8 -braille_dots_145678 16787705 0x10028F9 -braille_dots_245678 16787706 0x10028FA -braille_dots_1245678 16787707 0x10028FB -braille_dots_345678 16787708 0x10028FC -braille_dots_1345678 16787709 0x10028FD -braille_dots_2345678 16787710 0x10028FE -braille_dots_12345678 16787711 0x10028FF +.CE +.CS SunFA_Grave 268828416 0x1005FF00 SunFA_Circum 268828417 0x1005FF01 SunFA_Tilde 268828418 0x1005FF02 SunFA_Acute 268828419 0x1005FF03 SunFA_Diaeresis 268828420 0x1005FF04 Index: doc/listbox.n ================================================================== --- doc/listbox.n +++ doc/listbox.n @@ -561,11 +561,11 @@ .IP [16] In \fBextended\fR mode, the Escape key cancels the most recent selection and restores all the elements in the selected range to their previous selection state. .IP [17] -Control-slash selects everything in the widget, except in +Control-/ selects everything in the widget, except in \fBsingle\fR and \fBbrowse\fR modes, in which case it selects the active element and deselects everything else. .IP [18] Control-backslash deselects everything in the widget, except in \fBbrowse\fR mode where it has no effect. Index: doc/menu.n ================================================================== --- doc/menu.n +++ doc/menu.n @@ -38,11 +38,11 @@ which specifies whether or not the menu should include a tear-off entry at the top. If so, it will exist as entry 0 of the menu and the other entries will number starting at 1. The default menu bindings arrange for the menu to be torn off when the tear-off entry is invoked. -This option is ignored under Aqua/Mac OS X, where menus cannot +This option is ignored under Aqua/MacOS, where menus cannot be torn off. .OP \-tearoffcommand tearOffCommand TearOffCommand If this option has a non-empty value, then it specifies a Tcl command to invoke whenever the menu is torn off. The actual command will consist of the value of this option, followed by a space, followed @@ -52,11 +52,11 @@ .QW "\fBa b\fR" and menu \fB.x.y\fR is torn off to create a new menu \fB.x.tearoff1\fR, then the command .QW "\fBa b .x.y .x.tearoff1\fR" will be invoked. -This option is ignored under Aqua/Mac OS X, where menus cannot +This option is ignored under Aqua/MacOS, where menus cannot be torn off. .OP \-title title Title The string will be used to title the window created when this menu is torn off. If the title is NULL, then the window will have the title of the menubutton or the text of the cascade item from which this menu @@ -314,31 +314,35 @@ any of the following forms: .TP 12 \fBactive\fR . Indicates the entry that is currently active. If no entry is -active then this form is equivalent to \fBnone\fR. This form may +active then this form is equivalent to \fB{}\fR. This form may not be abbreviated. .TP 12 \fBend\fR . Indicates the bottommost entry in the menu. If there are no -entries in the menu then this form is equivalent to \fBnone\fR. +entries in the menu then this form is equivalent to \fB{}\fR. This form may not be abbreviated. .TP 12 \fBlast\fR . Same as \fBend\fR. .TP 12 -\fBnone\fR +\fB{}\fR . Indicates .QW "no entry at all" ; this is used most commonly with the \fBactivate\fR option to deactivate all the entries in the -menu. In most cases the specification of \fBnone\fR causes +menu. In most cases the specification of \fB{}\fR causes nothing to happen in the widget command. +.TP 12 +\fBnone\fR +. +Same as \fB{}\fR This form may not be abbreviated. .TP 12 \fB@\fInumber\fR . In this form, \fInumber\fR is treated as a y-coordinate in the @@ -369,11 +373,11 @@ \fIpathName \fBactivate \fIindex\fR . Change the state of the entry indicated by \fIindex\fR to \fBactive\fR and redisplay it using its active colors. Any previously-active entry is deactivated. If \fIindex\fR -is specified as \fBnone\fR, or if the specified entry is +is specified as \fBnone\fR or \fB{}\fR, or if the specified entry is disabled, then the menu ends up with no active entry. Returns an empty string. .TP \fIpathName \fBadd \fItype \fR?\fIoption value option value ...\fR? . @@ -445,11 +449,11 @@ information on the format of this list). .TP \fIpathName \fBindex \fIindex\fR . Returns the numerical index corresponding to \fIindex\fR, or -\fBnone\fR if \fIindex\fR was specified as \fBnone\fR. +\fBnone\fR if \fIindex\fR was specified as \fBnone\fR or \fB{}\fR. .TP \fIpathName \fBinsert \fIindex type \fR?\fIoption value option value ...\fR? . Same as the \fBadd\fR widget command except that it inserts the new entry just before the entry given by \fIindex\fR, instead of appending @@ -521,22 +525,22 @@ supported by all entry types. .TP \fB\-activebackground \fIvalue\fR . Specifies a background color to use for displaying this entry when it -is active. -If this option is specified as an empty string (the default), then the +is active. This option is ignored on Aqua/MacOS. +If it is specified as an empty string (the default), then the \fB\-activebackground\fR option for the overall menu is used. If the \fBtk_strictMotif\fR variable has been set to request strict Motif compliance, then this option is ignored and the \fB\-background\fR option is used in its place. This option is not available for separator or tear-off entries. .TP \fB\-activeforeground \fIvalue\fR . Specifies a foreground color to use for displaying this entry when it -is active. +is active. This option is ignored on Aqua/macOS. If this option is specified as an empty string (the default), then the \fB\-activeforeground\fR option for the overall menu is used. This option is not available for separator or tear-off entries. .TP \fB\-accelerator \fIvalue\fR @@ -550,11 +554,12 @@ .TP \fB\-background \fIvalue\fR . Specifies a background color to use for displaying this entry when it is in the normal state (neither active nor disabled). -If this option is specified as an empty string (the default), then the +This option is ignored on Aqua/macOS. +If it is specified as an empty string (the default), then the \fB\-background\fR option for the overall menu is used. This option is not available for separator or tear-off entries. .TP \fB\-bitmap \fIvalue\fR . @@ -571,11 +576,11 @@ \fB\-columnbreak \fIvalue\fR . When this option is zero, the entry appears below the previous entry. When this option is one, the entry appears at the top of a new column in the menu. -This option is ignored on Aqua/Mac OS X, where menus are always a single +This option is ignored on Aqua/macOS, where menus are always a single column. .TP \fB\-command \fIvalue\fR . Specifies a Tcl command to execute when the menu entry is invoked. @@ -601,11 +606,12 @@ .TP \fB\-foreground \fIvalue\fR . Specifies a foreground color to use for displaying this entry when it is in the normal state (neither active nor disabled). -If this option is specified as an empty string (the default), then the +This option is ignored on Aqua/macOS. +If it is specified as an empty string (the default), then the \fB\-foreground\fR option for the overall menu is used. This option is not available for separator or tear-off entries. .TP \fB\-hidemargin \fIvalue\fR . Index: doc/pack.n ================================================================== --- doc/pack.n +++ doc/pack.n @@ -164,11 +164,11 @@ the packing order. If \fIwindow\fR has no content then an empty string is returned. .TP \fBpack slaves \fIwindow\fR . -Synonym for . \fBpack content \fIwindow\fR +Synonym for \fBpack content \fIwindow\fR. .SH "THE PACKER ALGORITHM" .PP For each container the packer maintains an ordered list of content windows called the \fIpacking list\fR. The \fB\-in\fR, \fB\-after\fR, and \fB\-before\fR configuration Index: doc/photo.n ================================================================== --- doc/photo.n +++ doc/photo.n @@ -99,10 +99,20 @@ . Specifies the height of the image, in pixels. This option is useful primarily in situations where the user wishes to build up the contents of the image piece by piece. A value of zero (the default) allows the image to expand or shrink vertically to fit the data stored in it. +.VS 8.7 +.TP +\fB\-metadata \fImetadata\fR +. +Set the metadata dictionary of the image. +Additional keys may be set within the metadata dictionary of the image, +if image data is processed due to a \fB\-file\fR or \fB\-data\fR options +and the driver outputs any metadata keys. +See section \fBMETADATA DICTIONARY\fR below. +.VE 8.7 .TP \fB\-palette \fIpalette-spec\fR . Specifies the resolution of the color cube to be allocated for displaying this image, and thus the number of colors used from the @@ -144,11 +154,11 @@ .TP \fIimageName \fBblank\fR . Blank the image; that is, set the entire image to have no data, so it will be displayed as transparent, and the background of whatever -window it is displayed in will show through. +window it is displayed in will show through. The metadata dict of the image is not changed. .TP \fIimageName \fBcget\fR \fIoption\fR . Returns the current value of the configuration option given by \fIoption\fR. @@ -167,10 +177,14 @@ one or more \fIoption\-value\fR pairs are specified, then the command modifies the given option(s) to have the given value(s); in this case the command returns an empty string. \fIOption\fR may have any of the values accepted by the \fBimage create\fR \fBphoto\fR command. +.VS 8.7 +Note: setting the \fB\-metadata\fR option without any other option +will not invoke the image format driver to recreate the bitmap. +.VE 8.7 .TP \fIimageName \fBcopy\fR \fIsourceImage\fR ?\fIoption value(s) ...\fR? . Copies a region from the image called \fIsourceImage\fR (which must be a photo image) to the image called \fIimageName\fR, possibly with @@ -285,13 +299,22 @@ .TP \fB\-grayscale\fR . If this options is specified, the data will not contain color information. All pixel data will be transformed into grayscale. -.RE .VS 8.7 .TP +\fB\-metadata\fR \fImetadata\fR +. +Image format handler may use metadata to be included in the returned +data string. +The specified \fImetadata\fR is passed to the driver for inclusion in the +data. +If no \fB\-metadata\fR option is given, the current metadata of the +image is used. +.VE 8.7 +.RE \fIimageName \fBget\fR \fIx y\fR ?\fB-withalpha\fR? . Returns the color of the pixel at coordinates (\fIx\fR,\fIy\fR) in the image as a list of three integers between 0 and 255, representing the red, green and blue components respectively. If the \fB-withalpha\fR @@ -320,10 +343,19 @@ \fIformat-name\fR will be used while searching for an image data format handler to read the data. Note: the value of this option must be a Tcl list. This means that the braces may be omitted if the argument has only one word. Also, instead of braces, double quotes may be used for quoting. +.VS 8.7 +.TP +\fB\-metadata\fR \fImetadata\fR +. +A specified \fImetadata\fR is passed to the image format driver when interpreting +the data. +Note: The current metadata of the image is not passed to the format driver +and is not changed by the command. +.VE 8.7 .TP \fB\-to \fIx1 y1\fR ?\fIx2 y2\fR? . Specifies the coordinates of the top-left corner (\fIx1\fR,\fIy1\fR) of the region of \fIimageName\fR into which the image data will be @@ -365,10 +397,19 @@ specified, the region extends from (\fIx1,y1\fR) to the bottom-right corner of the image in the image file. If all four coordinates are specified, they specify diagonally opposite corners or the region. The default, if this option is not specified, is the whole of the image in the image file. +.VS 8.7 +.TP +\fB\-metadata\fR \fImetadata\fR +. +A specified \fImetadata\fR is passed to the image format driver when interpreting +the data. +Note: The current metadata of the image is not passed to the format driver +and is not changed by the command. +.VE 8.7 .TP \fB\-shrink\fR . If this option, the size of \fIimageName\fR will be reduced, if necessary, so that the region into which the image file data are read @@ -458,10 +499,20 @@ .TP \fB\-grayscale\fR . If this options is specified, the data will not contain color information. All pixel data will be transformed into grayscale. +.VS 8.7 +.TP +\fB\-metadata\fR \fBmetadata\fR +. +Image format handler may use metadata to be included in the written file. +The specified \fImetadata\fR is passed to the driver for inclusion in the +file. +If no \fB\-metadata\fR option is given, the current metadata of the +image is used. +.VE 8.7 .RE .SH "IMAGE FORMATS" .PP The photo image code is structured to allow handlers for additional image file formats to be added easily. The photo image code maintains @@ -680,10 +731,43 @@ this option is used, it specifies the maximum number of shades of each primary color to try to allocate. It can also be used to force the image to be displayed in shades of gray, even on a color display, by giving a single number rather than three numbers separated by slashes. +.VS 8.7 +.SH "METADATA DICTIONARY" +.PP +Each image has a metadata dictionary property. +This dictionary is not relevant to the bitmap representation of the +image, but may contain additional information like resolution or +comments. +Image format drivers may output metadata when image data is +parsed, or may use metadata to be included in image files or formats. +.SS "METADATA KEYS" +.PP +Each image format driver supports an individual set of metadata dictionary +keys. Predefined keys are: +.TP +DPI +. +Horizontal image resolution in DPI as a double value. +Supported by format \fBpng\fR. +.TP +aspect +. +Aspect ratio horizontal divided by vertical as double value. +Supported by formats \fBgif\fR and \fBpng\fR. +.TP +comment +. +Image text comment. +Supported by formats \fBgif\fR and \fBpng\fR. +.PP +It is valid to set any key in the metadata dict. +A format driver will ignore keys it does not handle. +.PP +.VE 8.7 .SH CREDITS .PP The photo image type was designed and implemented by Paul Mackerras, based on his earlier photo widget and some suggestions from John Ousterhout. Index: doc/place.n ================================================================== --- doc/place.n +++ doc/place.n @@ -195,11 +195,11 @@ Returns a list of all the content windows for which \fIwindow\fR is the container. If there is no content for \fIwindow\fR then an empty string is returned. .TP \fBplace slaves \fIwindow\fR . -Synonym for . \fBplace content \fIwindow\fR +Synonym for \fBplace content \fIwindow\fR. .PP If the configuration of a window has been retrieved with \fBplace info\fR, that configuration can be restored later by first using \fBplace forget\fR to erase any existing information for the window and then invoking \fBplace configure\fR with ADDED doc/print.n Index: doc/print.n ================================================================== --- /dev/null +++ doc/print.n @@ -0,0 +1,63 @@ +.\" Text automatically generated by txt2man +'\" +'\" Copyright (c) 2021 Kevin Walzer/WordTech Communications LLC. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +.TH tk print n "" Tk "Tk Built-in Commands" +.so man.macros +.SH NAME +print \- Print canvas and text widgets using native dialogs and APIs. +.SH SYNOPSIS +\fBtk print \fIwindow\fR +. +.SH DESCRIPTION +.PP +The \fBtk print\fR command posts a dialog that allows users to print output +from the \fBcanvas\fR and \fBtext\fR widgets. The printing will be done using +platform-native APIs and dialogs where available. +.PP +The \fBcanvas\fR widget has long supported PostScript export and both +PostScript and text files can be sent directly to a printer on Unix-like +systems using the +.QW "lp" +and +.QW "lpr" +Unix commands, and the \fBtk print\fR command does not supersede that +functionality; it builds on it. The \fBtk print\fR command is a fuller +implementation that uses native dialogs on macOS and Windows, and a Tk-based +dialog that provides parallel functionality on X11. +.SH PLATFORM NOTES +.TP +\fBmacOS\fR +. +The Mac implementation uses native print dialogs and relies on the underlying +Common Unix Printing System (CUPS) to render text output from the text widget +and PostScript output from the canvas widget to the printer, to a PDF file, or +a PostScript file. +.TP +\fBWindows\fR +. +The Windows implementation is based on the GDI (Graphics Device Interface) +API. Because there are slight differences in how GDI and Tk's \fBcanvas\fR +widget display graphics, printed output from the \fBcanvas\fR on Windows may +not be identical to screen rendering. +.TP +\fBX11\fR +. +The X11 implementation uses a Tk GUI to configure print jobs for sending to a +printer via the +.QW "lpr" +or +.QW "lp" +commands. While these commands have a large number of parameters for +configuring print jobs, printers vary widely in how they support these +parameters. As a result, only printer selection and number of copies are +configured as arguments to the print command; many aspects of print rendering, +such as grayscale or color for the canvas, are instead configured when +PostScript is generated. +.SH "SEE ALSO" +canvas(n), text(n), tk(n) +.SH KEYWORDS +print, output, graphics, text, canvas Index: doc/spinbox.n ================================================================== --- doc/spinbox.n +++ doc/spinbox.n @@ -222,11 +222,11 @@ .PP Also, the \fB-validate\fR option will set itself to \fBnone\fR when the spinbox value gets changed because of adjustment of \fB-from\fR or \fB-to\fR and the \fB-validatecommand\fR returns false. For instance .CS - \fIspinbox pathName \-from 1 \-to 10 \-validate all \-vcmd {return 0}\fR + \fIspinbox pathName \-from 1 \-to 10 \-validate all \-validatecommand {return 0}\fR .CE will in fact set the \fB-validate\fR option to \fBnone\fR because the default value for the spinbox gets changed (due to the \fB-from\fR and \fB-to\fR options) to a value not accepted by the validation script. .PP ADDED doc/sysnotify.n Index: doc/sysnotify.n ================================================================== --- /dev/null +++ doc/sysnotify.n @@ -0,0 +1,56 @@ +.\" Text automatically generated by txt2man +'\" +'\" Copyright (c) 2020 Kevin Walzer/WordTech Communications LLC. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH tk sysnotify n "" Tk "Tk Built-In Commands" +.so man.macros +.SH NAME +sysnotify \- Creates a notification window with a title and message. +.SH SYNOPSIS +\fBtk sysnotify\fR \fItitle\fR \fImessage\fR +.BE +.SH DESCRIPTION +.PP +The \fBtk sysnotify\fR command creates a platform-specific system notification alert. Its intent is to provide a brief, unobtrusive notification to the user by popping up a window that briefly appears in a corner of the screen. +.SH EXAMPLE +.PP +Here is an example of the \fBtk sysnotify\fR code: +.PP +.CS +tk sysnotify "Alert" \e + "This is just a test of the Tk System Notification Code." +.CE +.SH PLATFORM NOTES +.PP +The macOS and Windows versions are native implementations using system +API's. The X11 version has a conditional dependency on libnotify, and +falls back to a Tcl-only implementation if libnotify is not installed. On +each platform the notification includes a platform-specific default image to +accompany the text. +.TP +\fBmacOS\fR +. +The macOS version will request permission from the user to authorize +notifications. This must be activated in Apple's System Preferences +Notifications section. +.RS +.PP +If deploying an application using the standalone version of Wish.app, +setting the bundle ID in the applications Info.plist file to begin with +.QW \fBcom\fR +seems necessary for notifications to work. Using a different prefix +for the bundle ID, such as something like +.QW \fBtk.tcl.tkchat\fR , +will cause notifications to silently fail. +.RE +.TP +\fBWindows\fR +. +The image is taken from the system tray, i.e., \fBsysnotify\fR can only be +called when a \fBsystray\fR was installed. +. +.SH KEYWORDS +notify, alert ADDED doc/systray.n Index: doc/systray.n ================================================================== --- /dev/null +++ doc/systray.n @@ -0,0 +1,65 @@ +.\" Text automatically generated by txt2man +'\" +'\" Copyright (c) 2020 Kevin Walzer/WordTech Communications LLC. +'\" +'\" See the file "license.terms" for information on usage and redistribution +'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. +'\" +.TH tk systray n "" Tk "Tk Built-In Commands" +.so man.macros +.SH NAME +systray \- Creates an icon display in the platform-specific system tray. +.SH SYNOPSIS +\fBtk systray create \fI-image image\fR \fI?-text text\fR? \fI?-button1 callback?\fR \fI?-button3 callback?\fR +.sp +\fBtk systray configure \fI?option? ?value option value ...?\fR +.sp +\fBtk systray destroy\fR +.BE +.BE +.SH DESCRIPTION +.PP +The \fBtk systray create\fR command creates an icon in the platform-specific +tray. The widget is configured with a Tk image for the icon display, an +optional string for display in a tooltip, and optional callbacks that are +bound to and . +.PP +The \fBtk systray configure\fR command sets one or more options of the systray +icon. Configurable options are the same as for the \fBcreate\fR subcommand. When +a single option name is given, the command returns the current valus of this +option. When no option is given this command returns the list of all options and +their current value. +.PP + The \fBtk systray destroy\fR command removes the icon from display and +deallocates it. +.PP +From a user-interface standpoint, only one icon per interpreter is +supported; attempts to create additional icons will return an error. The +existing tray icon can be modified with different images and +strings to indicate app state. Loading additional interpreters into a +running instance of Wish will allow additional icons to be displayed. +.SH EXAMPLE +.PP +Here is an example of the \fBtk systray\fR code: +.CS + image create photo book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw== + tk systray create -image book -text "tk systray sample" -button1 {puts "Here is the tk systray output"} -button3 {puts "here is alternate output"} +.CE +.PP +Here is an example of modifying the \fBtk systray\fR icon: +.CS + image create photo book_page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7 + tk systray configure -image book_page -text "Updated sample" -button1 {puts "Different output from the tk systray"} -button3 {puts "and more different output from the tk systray"} +.CE +.SH PLATFORM NOTES +.PP +The X11 implementation is supported on a "best efforts" basis because it is +dependent on the window manager. The "text" flag, which is implemented as +a tooltip, does not always display if the WM does not support such features; +the systray icon itself may not even display with some window managers. +.PP +On Windows, the Tk image provided in the \fI-image\fR option must be a +photo image. On other platforms either a bitmap image or a photo image +may be provided. +.SH KEYWORDS +image, callback Index: doc/text.n ================================================================== --- doc/text.n +++ doc/text.n @@ -1350,11 +1350,11 @@ are empty strings. .TP \fIpathName \fBimage \fIoption \fR?\fIarg ...\fR? . This command is used to manipulate embedded images. The behavior of the -command depends on the \fIoption\fR argument that follows the \fBtag\fR +command depends on the \fIoption\fR argument that follows the \fBimage\fR argument. The following forms of the command are currently supported: .RS .TP \fIpathName \fBimage cget \fIindex option\fR . @@ -2031,11 +2031,11 @@ In the descriptions below, .QW word is dependent on the value of the \fBtcl_wordchars\fR variable. See \fBtclvars\fR(n). .IP [1] -Clicking mouse button 1 positions the insertion cursor just before the +Clicking mouse button 1 positions the insertion cursor at the closest edge of the character underneath the mouse cursor, sets the input focus to this widget, and clears any selection in the widget. Dragging with mouse button 1 strokes out a selection between the insertion cursor and the character under the mouse. .IP [2] Index: doc/tk.n ================================================================== --- doc/tk.n +++ doc/tk.n @@ -83,10 +83,17 @@ .RE .TP \fBtk fontchooser \fIsubcommand\fR ... Controls the Tk font selection dialog. For more details see the \fBfontchooser\fR manual page. +.TP +\fBtk print \fIwindow\fR +. +The \fBtk print\fR command posts a dialog that allows users to print output +from the \fBcanvas\fR and \fBtext\fR widgets. The printing will be done using +platform-native APIs and dialogs where available. For more details see the +\fBprint\fR manual page. .TP \fBtk scaling \fR?\fB\-displayof \fIwindow\fR? ?\fInumber\fR? . Sets and queries the current scaling factor used by Tk to convert between physical units (for example, points, inches, or millimeters) and pixels. The @@ -109,10 +116,22 @@ after the scaling factor is changed will use the new scaling factor, but it is undefined whether existing widgets will resize themselves dynamically to accommodate the new scaling factor. .RE .TP +\fBtk sysnotify \fP \fItitle\fP? \fImessage\fP? +. +The \fBtk sysnotify\fP command creates a platform-specific system +notification alert. Its intent is to provide a brief, unobtrusive +notification to the user by popping up a window that briefly appears in a +corner of the screen. For more details see the \fBsysnotify\fR manual page. +.TP +\fBtk systray create\fP \fIsubcommand...\fP +. +The \fBtk systray\fP command creates an icon in the platform-specific +tray. For more details see the \fBsystray\fR manual page. +.TP \fBtk useinputmethods \fR?\fB\-displayof \fIwindow\fR? ?\fIboolean\fR? . Sets and queries the state of whether Tk should use XIM (X Input Methods) for filtering events. The resulting state is returned. XIM is used in some locales (i.e., Japanese, Korean), to handle special input devices. This @@ -125,11 +144,11 @@ . Returns the current Tk windowing system, one of \fBx11\fR (X11-based), \fBwin32\fR (MS Windows), or \fBaqua\fR (Mac OS X Aqua). .SH "SEE ALSO" -busy(n), fontchooser(n), send(n), winfo(n) +busy(n), fontchooser(n), print(n), send(n), sysnotify(n), systray(n), winfo(n) .SH KEYWORDS -application name, send +application name, print, send, sysnotify, systray '\" Local Variables: '\" mode: nroff '\" End: Index: doc/tk_mac.n ================================================================== --- doc/tk_mac.n +++ doc/tk_mac.n @@ -216,15 +216,21 @@ The Aqua/Mac OS X defines additional dialogs that applications should support. .TP \fB::tk::mac::standardAboutPanel\fR . -Brings the standard Cocoa about panel to the front, with all its information -filled in from your application bundle files (standard about panel with no -options specified). See Apple Technote TN2179 and the AppKit documentation for --[NSApplication orderFrontStandardAboutPanelWithOptions:] for details on the -Info.plist keys and app bundle files used by the about panel. +Brings the standard Cocoa about panel to the front with information filled in +from the application bundle files. The panel displays the application icon and +the values associated to the info.plist keys named CFBundleName, +CFBundleShortVersionString, NSAboutPanelOptionVersion and +NSHumanReadableCopyright. If a file named \fICredits.html\fR or +\fICredits.rtf\fR exists in the bundle's Resources directory then its contents +will be displayed in a scrolling text box at the bottom of the dialog. See the +documentation for -[NSApplication orderFrontStandardAboutPanelWithOptions:] +for more details. A hook is also provided for a custom About dialog. If a Tcl +proc named tkAboutDialog is defined in the main interpreter then that +procedure will be called instead of opening the standardAboutPanel. .SH "SYSTEM CONFIGURATION" .PP There are a number of additional global configuration options that control the details of how Tk renders by default. .TP Index: doc/tkvars.n ================================================================== --- doc/tkvars.n +++ doc/tkvars.n @@ -24,11 +24,11 @@ file that is normally processed whenever a Tk application starts up, plus other files containing procedures that implement default behaviors for widgets. .RS .PP -The initial value of \fBtcl_library\fR is set when Tk is added to +The initial value of \fBtk_library\fR is set when Tk is added to an interpreter; this is done by searching several different directories until one is found that contains an appropriate Tk startup script. If the \fBTK_LIBRARY\fR environment variable exists, then the directory it names is checked first. If \fBTK_LIBRARY\fR is not set or does not refer to an appropriate @@ -48,11 +48,11 @@ The patch level is incremented for each new release or patch, and it uniquely identifies an official version of Tk. .RS .PP This value is normally the same as the result of -.QW "\fBpackage require\fR \fBTk\fR" . +.QW "\fBpackage require\fR \fBtk\fR" . .RE .TP \fBtk_strictMotif\fR . This variable is set to zero by default. Index: doc/toplevel.n ================================================================== --- doc/toplevel.n +++ doc/toplevel.n @@ -38,11 +38,13 @@ .VE "8.7, TIP262" .OP \-class class Class Specifies a class for the window. This class will be used when querying the option database for the window's other options, and it will also be used later for -other purposes such as bindings. +other purposes such as bindings. Some window managers display the +class name for windows in their dock while some others display the +window title. The \fB\-class\fR option may not be changed with the \fBconfigure\fR widget command. .OP \-colormap colormap Colormap Specifies a colormap to use for the window. The value may be either \fBnew\fR, in which case a new colormap is Index: doc/ttk_button.n ================================================================== --- doc/ttk_button.n +++ doc/ttk_button.n @@ -46,12 +46,14 @@ .\" .OP \-anchor anchor Anchor .\" .OP \-relief relief Relief .SH "WIDGET COMMAND" .PP In addition to the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -commands, buttons support the following additional widget commands: +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +button widgets support the following additional commands: .TP \fIpathName \fBinvoke\fR Invokes the command associated with the button. .SH "STANDARD STYLES" .PP Index: doc/ttk_checkbutton.n ================================================================== --- doc/ttk_checkbutton.n +++ doc/ttk_checkbutton.n @@ -35,13 +35,14 @@ The name of a global variable whose value is linked to the widget. Defaults to the widget pathname if not specified. .SH "WIDGET COMMAND" .PP In addition to the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -commands, checkbuttons support the following additional -widget commands: +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +checkbutton widgets support the following additional commands: .TP \fIpathname\fB invoke\fR Toggles between the selected and deselected states and evaluates the associated \fB\-command\fR. If the widget is currently selected, sets the \fB\-variable\fR Index: doc/ttk_combobox.n ================================================================== --- doc/ttk_combobox.n +++ doc/ttk_combobox.n @@ -53,19 +53,15 @@ .OP \-width width Width Specifies an integer value indicating the desired width of the entry window, in average-size characters of the widget's font. .SH "WIDGET COMMAND" .PP -The following subcommands are possible for combobox widgets: -'\".TP -'\"\fIpathName \fBcget\fR \fIoption\fR -'\"Returns the current value of the specified \fIoption\fR. -'\"See \fIttk::widget(n)\fR. -'\".TP -'\"\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -'\"Modify or query widget options. -'\"See \fIttk::widget(n)\fR. +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +combobox widgets support the following additional commands: .TP \fIpathName \fBcurrent\fR ?\fInewIndex\fR? If \fInewIndex\fR is supplied, sets the combobox value to the element at position \fInewIndex\fR in the list of \fB\-values\fR (in addition to integers, the \fBend\fR index is supported and indicates @@ -73,41 +69,22 @@ Otherwise, returns the index of the current value in the list of \fB\-values\fR or \fB\-1\fR if the current value does not appear in the list. .TP \fIpathName \fBget\fR Returns the current value of the combobox. -'\".TP -'\"\fIpathName \fBidentify \fIx y\fR -'\"Returns the name of the element at position \fIx\fR, \fIy\fR. -'\"See \fIttk::widget(n)\fR. -'\".TP -'\"\fIpathName \fBinstate \fIstateSpec\fR ?\fIscript\fR? -'\"Test the widget state. -'\"See \fIttk::widget(n)\fR. .TP \fIpathName \fBset\fR \fIvalue\fR Sets the value of the combobox to \fIvalue\fR. -'\".TP -'\"\fIpathName \fBstate\fR ?\fIstateSpec\fR? -'\"Modify or query the widget state. -'\"See \fIttk::widget(n)\fR. .PP The combobox widget also supports the following \fBttk::entry\fR -widget subcommands (see \fIttk::entry(n)\fR for details): +widget commands: .DS .ta 5.5c 11c \fBbbox\fR \fBdelete\fR \fBicursor\fR \fBindex\fR \fBinsert\fR \fBselection\fR \fBxview\fR .DE -The combobox widget also supports the following generic \fBttk::widget\fR -widget subcommands (see \fIttk::widget(n)\fR for details): -.DS -.ta 5.5c 11c -\fBcget\fR \fBconfigure\fR \fBidentify\fR -\fBinstate\fR \fBstate\fR -.DE .SH "VIRTUAL EVENTS" .PP The combobox widget generates a \fB<>\fR virtual event when the user selects an element from the list of values. If the selection action unposts the listbox, Index: doc/ttk_entry.n ================================================================== --- doc/ttk_entry.n +++ doc/ttk_entry.n @@ -137,11 +137,15 @@ .QW \fBsel.l\fR . In general, out-of-range indices are automatically rounded to the nearest legal value. .SH "WIDGET COMMAND" .PP -The following subcommands are possible for entry widgets: +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR, \fBstyle\fR and \fBxview\fR +commands (see \fBttk::widget\fR), +entry widgets support the following additional commands: .TP \fIpathName \fBbbox \fIindex\fR Returns a list of four numbers describing the bounding box of the character given by \fIindex\fR. The first two elements of the list give the x and y coordinates of @@ -148,18 +152,10 @@ the upper-left corner of the screen area covered by the character (in pixels relative to the widget) and the last two elements give the width and height of the character, in pixels. The bounding box may refer to a region outside the visible area of the window. -'\".TP -'\"\fIpathName \fBcget\fR \fIoption\fR -'\"Returns the current value of the specified \fIoption\fR. -'\"See \fIttk::widget(n)\fR. -'\".TP -'\"\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -'\"Modify or query widget options. -'\"See \fIttk::widget(n)\fR. .TP \fIpathName \fBdelete \fIfirst \fR?\fIlast\fR? Delete one or more elements of the entry. \fIFirst\fR is the index of the first character to delete, and \fIlast\fR is the index of the character just after the last @@ -172,25 +168,17 @@ Returns the entry's string. .TP \fIpathName \fBicursor \fIindex\fR Arrange for the insert cursor to be displayed just before the character given by \fIindex\fR. Returns the empty string. -'\".TP -'\"\fIpathName \fBidentify \fIx y\fR -'\"Returns the name of the element at position \fIx\fR, \fIy\fR, -'\"or the empty string if the coordinates are outside the window. .TP \fIpathName \fBindex\fI index\fR Returns the numerical index corresponding to \fIindex\fR. .TP \fIpathName \fBinsert \fIindex string\fR Insert \fIstring\fR just before the character indicated by \fIindex\fR. Returns the empty string. -'\".TP -'\"\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR? -'\"Test the widget state. -'\"See \fIttk::widget(n)\fR. .TP \fIpathName \fBselection \fIoption arg\fR This command is used to adjust the selection within an entry. It has several forms, depending on \fIoption\fR: .RS @@ -209,29 +197,17 @@ the one indexed by \fIstart\fR and ending with the one just before \fIend\fR. If \fIend\fR refers to the same character as \fIstart\fR or an earlier one, then the entry's selection is cleared. .RE -'\".TP -'\"\fIpathName \fBstate\fR ?\fIstateSpec\fR? -'\"Modify or query the widget state. -'\"See \fIttk::widget(n)\fR. .TP \fIpathName \fBvalidate\fR Force revalidation, independent of the conditions specified by the \fB\-validate\fR option. Returns 0 if validation fails, 1 if it succeeds. Sets or clears the \fBinvalid\fR state accordingly. See \fBVALIDATION\fR below for more details. -.PP -The entry widget also supports the following generic \fBttk::widget\fR -widget subcommands (see \fIttk::widget(n)\fR for details): -.DS -.ta 5.5c 11c -\fBcget\fR \fBconfigure\fR \fBidentify\fR -\fBinstate\fR \fBstate\fR \fBxview\fR -.DE .SH VALIDATION .PP The \fB\-validate\fR, \fB\-validatecommand\fR, and \fB\-invalidcommand\fR options are used to enable entry widget validation. .SS "VALIDATION MODES" Index: doc/ttk_frame.n ================================================================== --- doc/ttk_frame.n +++ doc/ttk_frame.n @@ -33,13 +33,14 @@ If specified, the widget's requested width in pixels. .OP \-height height Height If specified, the widget's requested height in pixels. .SH "WIDGET COMMAND" .PP -Supports the standard widget commands -\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR; -see \fIttk::widget(n)\fR. +Frame widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .SH "NOTES" .PP Note that if the \fBpack\fR, \fBgrid\fR, or other geometry managers are used to manage the children of the \fBframe\fR, by the GM's requested size will normally take precedence Index: doc/ttk_label.n ================================================================== --- doc/ttk_label.n +++ doc/ttk_label.n @@ -40,13 +40,14 @@ then automatic wrapping is not performed; otherwise the text is split into lines such that no line is longer than the specified value. .SH "WIDGET COMMAND" .PP -Supports the standard widget commands -\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR; -see \fIttk::widget(n)\fR. +Label widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .SH "STYLING OPTIONS" .PP The class name for a \fBttk::label\fP is \fBTLabel\fP. .PP Dynamic states: \fBdisabled\fP, \fBreadonly\fP. Index: doc/ttk_labelframe.n ================================================================== --- doc/ttk_labelframe.n +++ doc/ttk_labelframe.n @@ -60,13 +60,14 @@ sets the keyboard focus to the first child of the \fBttk::labelframe\fR widget. .OP \-width width Width If specified, the widget's requested width in pixels. .SH "WIDGET COMMAND" .PP -Supports the standard widget commands -\fBconfigure\fR, \fBcget\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR; -see \fIttk::widget(n)\fR. +Labelframe widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .SH "STYLING OPTIONS" .PP The class name for a \fBttk::labelframe\fP is \fBTLabelframe\fP. The text label has a class of \fBTLabelframe.Label\fP. Index: doc/ttk_menubutton.n ================================================================== --- doc/ttk_menubutton.n +++ doc/ttk_menubutton.n @@ -36,13 +36,14 @@ .\" not documented: may go away: .\" .OP \-anchor anchor Anchor .\" .OP \-padding padding Pad .SH "WIDGET COMMAND" .PP -Menubutton widgets support the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -methods. No other widget methods are used. +Menubutton widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .SH "STANDARD STYLES" .PP \fBTtk::menubutton\fR widgets support the \fBToolbutton\fR style in all standard themes, which is useful for creating widgets for toolbars. .SH "STYLING OPTIONS" Index: doc/ttk_notebook.n ================================================================== --- doc/ttk_notebook.n +++ doc/ttk_notebook.n @@ -100,23 +100,23 @@ .QW \fBend\fR , which returns the number of tabs (only valid for .QW "\fIpathname \fBindex\fR" ). .SH "WIDGET COMMAND" +.PP +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +notebook widgets support the following additional commands: .TP \fIpathname \fBadd \fIwindow\fR ?\fIoptions...\fR? Adds a new tab to the notebook. See \fBTAB OPTIONS\fR for the list of available \fIoptions\fR. If \fIwindow\fR is currently managed by the notebook but hidden, it is restored to its previous position. .TP -\fIpathname \fBconfigure\fR ?\fIoptions\fR? -See \fIttk::widget(n)\fR. -.TP -\fIpathname \fBcget \fIoption\fR -See \fIttk::widget(n)\fR. -.TP \fIpathname \fBforget \fItabid\fR Removes the tab specified by \fItabid\fR, unmaps and unmanages the associated window. .TP \fIpathname \fBhide \fItabid\fR @@ -149,23 +149,17 @@ or the name of a managed subwindow. If \fIsubwindow\fR is already managed by the notebook, moves it to the specified position. See \fBTAB OPTIONS\fR for the list of available options. .TP -\fIpathname \fBinstate \fIstatespec \fR?\fIscript...\fR? -See \fIttk::widget(n)\fR. -.TP \fIpathname \fBselect\fR ?\fItabid\fR? Selects the specified tab. The associated content window will be displayed, and the previously-selected window (if different) is unmapped. If \fItabid\fR is omitted, returns the widget name of the currently selected pane. .TP -\fIpathname \fBstate\fR ?\fIstatespec\fR? -See \fIttk::widget(n)\fR. -.TP \fIpathname \fBtab \fItabid\fR ?\fI\-option \fR?\fIvalue ...\fR Query or modify the options of the specific tab. If no \fI\-option\fR is specified, returns a dictionary of the tab option values. If one \fI\-option\fR is specified, Index: doc/ttk_panedwindow.n ================================================================== --- doc/ttk_panedwindow.n +++ doc/ttk_panedwindow.n @@ -46,13 +46,16 @@ .OP \-weight weight Weight An integer specifying the relative stretchability of the pane. When the paned window is resized, the extra space is added or subtracted to each pane proportionally to its \fB\-weight\fR. .SH "WIDGET COMMAND" -Supports the standard \fBconfigure\fR, \fBcget\fR, \fBstate\fR, -and \fBinstate\fR commands; see \fIttk::widget(n)\fR for details. -Additional commands: +.PP +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +panedwindow widgets support the following additional commands: .TP \fIpathname \fBadd \fIsubwindow options...\fR Adds a new pane to the window. See \fBPANE OPTIONS\fR for the list of available options. .TP @@ -104,18 +107,10 @@ .\" Full story: "total size" is either the -height (resp -width), .\" or the actual window height (resp actual window width), .\" depending on which changed most recently. Returns the new position of sash number \fIindex\fR. .\" Full story: new position may be different than the requested position. -.PP -The panedwindow widget also supports the following generic \fBttk::widget\fR -widget subcommands (see \fIttk::widget(n)\fR for details): -.DS -.ta 5.5c 11c -\fBcget\fR \fBconfigure\fR -\fBinstate\fR \fBstate\fR -.DE .SH "VIRTUAL EVENTS" .PP The panedwindow widget generates an \fB<>\fR virtual event on LeaveNotify/NotifyInferior events, because Tk does not execute binding scripts for events when the pointer crosses from a parent to a child. The Index: doc/ttk_progressbar.n ================================================================== --- doc/ttk_progressbar.n +++ doc/ttk_progressbar.n @@ -64,33 +64,22 @@ If specified to an existing variable, the \fB\-value\fR of the progress bar is automatically set to the value of the variable whenever the latter is modified. .SH "WIDGET COMMAND" .PP -.TP -\fIpathName \fBcget \fIoption\fR -Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR. -.TP -\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -Modify or query widget options; see \fIttk::widget(n)\fR. -.TP -\fIpathName \fBidentify \fIx y\fR -Returns the name of the element at position \fIx\fR, \fIy\fR. -See \fIttk::widget(n)\fR. -.TP -\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR? -Test the widget state; see \fIttk::widget(n)\fR. +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +progressbar widgets support the following additional commands: .TP \fIpathName \fBstart\fR ?\fIinterval\fR? Begin autoincrement mode: schedules a recurring timer event that calls \fBstep\fR every \fIinterval\fR milliseconds. If omitted, \fIinterval\fR defaults to 50 milliseconds (20 steps/second). .TP -\fIpathName \fBstate\fR ?\fIstateSpec\fR? -Modify or query the widget state; see \fIttk::widget(n)\fR. -.TP \fIpathName \fBstep\fR ?\fIamount\fR? Increments the \fB\-value\fR by \fIamount\fR. \fIamount\fR defaults to 1.0 if omitted. .TP \fIpathName \fBstop\fR Index: doc/ttk_radiobutton.n ================================================================== --- doc/ttk_radiobutton.n +++ doc/ttk_radiobutton.n @@ -35,13 +35,14 @@ The name of a global variable whose value is linked to the widget. Default value is \fB::selectedButton\fR. .SH "WIDGET COMMAND" .PP In addition to the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -commands, radiobuttons support the following additional -widget commands: +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +radiobutton widgets support the following additional commands: .TP \fIpathname\fB invoke\fR Sets the \fB\-variable\fR to the \fB\-value\fR, selects the widget, and evaluates the associated \fB\-command\fR. Returns the result of the \fB\-command\fR, or the empty Index: doc/ttk_scale.n ================================================================== --- doc/ttk_scale.n +++ doc/ttk_scale.n @@ -49,59 +49,40 @@ value of the variable changes, the scale will update to reflect this value. Whenever the scale is manipulated interactively, the variable will be modified to reflect the scale's new value. .SH "WIDGET COMMAND" .PP -.TP -\fIpathName \fBcget \fIoption\fR -. -Returns the current value of the specified \fIoption\fR; see -\fIttk::widget(n)\fR. -.TP -\fIpathName \fBconfigure \fR?\fIoption\fR? ?\fIvalue option value ...\fR? -. -Modify or query widget options; see \fIttk::widget(n)\fR. +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +scale widgets support the following additional commands: .TP \fIpathName \fBget \fR?\fIx y\fR? -. Get the current value of the \fB\-value\fR option, or the value corresponding to the coordinates \fIx,y\fR if they are specified. \fIX\fR and \fIy\fR are pixel coordinates relative to the scale widget origin. .TP -\fIpathName \fBidentify \fIx y\fR -Returns the name of the element at position \fIx\fR, \fIy\fR. -See \fIttk::widget(n)\fR. -.TP -\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR? -. -Test the widget state; see \fIttk::widget(n)\fR. -.TP \fIpathName \fBset \fIvalue\fR -. Set the value of the widget (i.e. the \fB\-value\fR option) to \fIvalue\fR. The value will be clipped to the range given by the \fB\-from\fR and \fB\-to\fR options. Note that setting the linked variable (i.e. the variable named in the \fB\-variable\fR option) does not cause such clipping. -.TP -\fIpathName \fBstate\fR ?\fIstateSpec\fR? -. -Modify or query the widget state; see \fIttk::widget(n)\fR. .SH "INTERNAL COMMANDS" .PP .TP \fIpathName \fBcoords \fR?\fIvalue\fR? -. Get the coordinates corresponding to \fIvalue\fR, or the coordinates corresponding to the current value of the \fB\-value\fR option if \fIvalue\fR is omitted. .SH "STYLING OPTIONS" .PP The class name for a \fBttk::scale\fP is \fBTScale\fP. .PP Dynamic states: \fBactive\fP. .PP -\fBTProgressbar\fP styling options configurable with \fBttk::style\fP +\fBTScale\fP styling options configurable with \fBttk::style\fP are: .PP \fB\-background\fP \fIcolor\fP .br \fB\-borderwidth\fP \fIamount\fP Index: doc/ttk_scrollbar.n ================================================================== --- doc/ttk_scrollbar.n +++ doc/ttk_scrollbar.n @@ -45,36 +45,25 @@ .OP \-orient orient Orient One of \fBhorizontal\fR or \fBvertical\fR. Specifies the orientation of the scrollbar. .SH "WIDGET COMMAND" .PP -.TP -\fIpathName \fBcget \fIoption\fR -Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR. -.TP -\fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -Modify or query widget options; see \fIttk::widget(n)\fR. +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +commands (see \fBttk::widget\fR), +scrollbar widgets support the following additional commands: .TP \fIpathName \fBget\fR Returns the scrollbar settings in the form of a list whose elements are the arguments to the most recent \fBset\fR widget command. .TP -\fIpathName \fBidentify \fIx y\fR -Returns the name of the element at position \fIx\fR, \fIy\fR. -See \fIttk::widget(n)\fR. -.TP -\fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR? -Test the widget state; see \fIttk::widget(n)\fR. -.TP \fIpathName \fBset \fIfirst last\fR This command is normally invoked by the scrollbar's associated widget from an \fB\-xscrollcommand\fR or \fB\-yscrollcommand\fR callback. Specifies the visible range to be displayed. \fIfirst\fR and \fIlast\fR are real fractions between 0 and 1. -.TP -\fIpathName \fBstate\fR ?\fIstateSpec\fR? -Modify or query the widget state; see \fIttk::widget(n)\fR. .SH "INTERNAL COMMANDS" .PP The following widget commands are used internally by the \fBTScrollbar\fP widget class bindings. .TP Index: doc/ttk_separator.n ================================================================== --- doc/ttk_separator.n +++ doc/ttk_separator.n @@ -24,13 +24,14 @@ .OP \-orient orient Orient One of \fBhorizontal\fR or \fBvertical\fR. Specifies the orientation of the separator. .SH "WIDGET COMMAND" .PP -Separator widgets support the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -methods. No other widget methods are used. +Separator widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .PP .SH "STYLING OPTIONS" .PP The class name for a \fBttk::separator\fP is \fBTSeparator\fP. .PP Index: doc/ttk_sizegrip.n ================================================================== --- doc/ttk_sizegrip.n +++ doc/ttk_sizegrip.n @@ -21,13 +21,14 @@ \-class \-cursor \-style \-takefocus .SE .SH "WIDGET COMMAND" .PP -Sizegrip widgets support the standard -\fBcget\fR, \fBconfigure\fR, \fBidentify\fR, \fBinstate\fR, and \fBstate\fR -methods. No other widget methods are used. +Sizegrip widgets support the standard commands +\fBcget\fR, \fBconfigure\fR, \fBidentify element\fR, \fBinstate\fR, +\fBstate\fR and \fBstyle\fR +(see \fBttk::widget\fR). .SH "PLATFORM-SPECIFIC NOTES" .PP On Mac OSX, toplevel windows automatically include a built-in size grip by default. Adding a \fBttk::sizegrip\fR there is harmless, since Index: doc/ttk_style.n ================================================================== --- doc/ttk_style.n +++ doc/ttk_style.n @@ -25,16 +25,24 @@ By default, the style name is the same as the widget's class; this may be overridden by the \fB\-style\fR option. .PP A \fItheme\fR is a collection of elements and styles which controls the overall look and feel of an application. +The +.QW . +style is the theme root style on which derived styles are based. .SH DESCRIPTION .PP The \fBttk::style\fR command takes the following arguments: .TP \fBttk::style configure \fIstyle\fR ?\fI\-option\fR ?\fIvalue option value...\fR? ? Sets the default value of the specified option(s) in \fIstyle\fR. +If \fIstyle\fR does not exist, it is created. +If only \fIstyle\fR and \fI-option\fR are specified, get the default value +for option \fI-option\fR of style \fIstyle\fR. +If only \fIstyle\fR is specified, get the default value for all options +of style \fIstyle\fR. .TP \fBttk::style element\fR \fIargs\fR .RS .TP \fBttk::style element create\fR \fIelementName\fR \fItype\fR ?\fIargs...\fR? @@ -66,16 +74,22 @@ .QW normal state). If the \fIdefault\fR argument is present, it is used as a fallback value in case no specification for \fI\-option\fR is found. .\" Otherwise -- signal error? return empty string? Leave unspecified for now. +If \fIstyle\fR does not exist, it is created. .TP \fBttk::style map \fIstyle\fR ?\fI\-option\fB { \fIstatespec value...\fB }\fR? -Sets dynamic values of the specified option(s) in \fIstyle\fR. +Sets dynamic (state dependent) values of the specified option(s) in \fIstyle\fR. Each \fIstatespec / value\fR pair is examined in order; the value corresponding to the first matching \fIstatespec\fR is used. +If \fIstyle\fR does not exist, it is created. +If only \fIstyle\fR and \fI-option\fR are specified, get the dynamic values +for option \fI-option\fR of style \fIstyle\fR. +If only \fIstyle\fR is specified, get the dynamic values for all options +of style \fIstyle\fR. .TP \fBttk::style theme\fR \fIargs\fR .RS .TP \fBttk::style theme create\fR \fIthemeName\fR ?\fB\-parent \fIbasedon\fR? ?\fB\-settings \fIscript...\fR ? @@ -91,10 +105,14 @@ \fBttk::style theme settings \fIthemeName\fR \fIscript\fR Temporarily sets the current theme to \fIthemeName\fR, evaluate \fIscript\fR, then restore the previous theme. Typically \fIscript\fR simply defines styles and elements, though arbitrary Tcl code may appear. +.TP +\fBttk::style theme styles\fR ?\fIthemeName\fR? +Returns a list of all styles in \fIthemeName\fR. If \fIthemeName\fR +is omitted, the current theme is used. .TP \fBttk::style theme use\fR ?\fIthemeName\fR? Without an argument the result is the name of the current theme. Otherwise this command sets the current theme to \fIthemeName\fR, and refreshes all widgets. Index: doc/ttk_treeview.n ================================================================== --- doc/ttk_treeview.n +++ doc/ttk_treeview.n @@ -90,10 +90,15 @@ \fBNOTE:\fR Column #0 always refers to the tree column, even if \fB\-show tree\fR is not specified. .RE .SH "WIDGET COMMAND" .PP +In addition to the standard +\fBcget\fR, \fBconfigure\fR, \fBinstate\fR, +\fBstate\fR, \fBstyle\fR, \fBxview\fR and \fByview\fR +commands (see \fBttk::widget\fR), +treeview widgets support the following additional commands: .TP \fIpathname \fBbbox \fIitem\fR ?\fIcolumn\fR? Returns the bounding box (relative to the treeview widget's window) of the specified \fIitem\fR in the form \fIx y width height\fR. @@ -100,13 +105,10 @@ If \fIcolumn\fR is specified, returns the bounding box of that cell. If the \fIitem\fR is not visible (i.e., if it is a descendant of a closed item or is scrolled offscreen), returns the empty list. .TP -\fIpathname \fBcget \fIoption\fR -Returns the current value of the specified \fIoption\fR; see \fIttk::widget(n)\fR. -.TP \fIpathname \fBchildren \fIitem\fR ?\fInewchildren\fR? If \fInewchildren\fR is not specified, returns the list of children belonging to \fIitem\fR. .RS .PP @@ -158,13 +160,10 @@ column separator. .PP Use \fIpathname column #0\fR to configure the tree column. .RE .TP -\fIpathname \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -Modify or query widget options; see \fIttk::widget(n)\fR. -.TP \fIpathname \fBdelete \fIitemList\fR Deletes each of the items in \fIitemList\fR and all of their descendants. The root item may not be deleted. See also: \fBdetach\fR. .TP @@ -270,13 +269,10 @@ \fIpathname \fBinsert\fR returns the item identifier of the newly created item. See \fBITEM OPTIONS\fR for the list of available options. .RE .TP -\fIpathname \fBinstate \fIstatespec\fR ?\fIscript\fR? -Test the widget state; see \fIttk::widget(n)\fR. -.TP \fIpathname \fBitem \fIitem\fR ?\fI\-option \fR?\fIvalue \-option value...\fR? Query or modify the options for the specified \fIitem\fR. If no \fI\-option\fR is specified, returns a dictionary of option/value pairs. If a single \fI\-option\fR is specified, @@ -336,13 +332,10 @@ With two arguments, returns the current value of the specified \fIcolumn\fR. With three arguments, sets the value of column \fIcolumn\fR in item \fIitem\fR to the specified \fIvalue\fR. See also \fBCOLUMN IDENTIFIERS\fR. .TP -\fIpathname \fBstate\fR ?\fIstateSpec\fR? -Modify or query the widget state; see \fIttk::widget(n)\fR. -.TP \fIpathName \fBtag \fIargs...\fR .RS .TP \fIpathName \fBtag add \fItag items\fR Adds the specified \fItag\fR to each of the listed \fIitems\fR. @@ -396,17 +389,10 @@ Removes the specified \fItag\fR from each of the listed \fIitems\fR. If \fIitems\fR is omitted, removes \fItag\fR from each item in the tree. If \fItag\fR is not present for a particular item, then the \fB\-tags\fR for that item are unchanged. .RE -.PP -The treeview widget also supports the following generic \fBttk::widget\fR -widget subcommands (see \fIttk::widget(n)\fR for details): -.DS -.ta 5.5c 11c -\fBxview\fR \fByview\fR -.DE .SH "ITEM OPTIONS" .PP The following item options may be specified for items in the \fBinsert\fR and \fBitem\fR widget commands. .OP \-text text Text Index: doc/ttk_widget.n ================================================================== --- doc/ttk_widget.n +++ doc/ttk_widget.n @@ -172,16 +172,14 @@ but the \fBstate\fR widget command does not affect the \fB\-state\fR option. .SH COMMANDS .TP \fIpathName \fBcget \fIoption\fR -. Returns the current value of the configuration option given by \fIoption\fR. .TP \fIpathName \fBconfigure\fR ?\fIoption\fR? ?\fIvalue option value ...\fR? -. Query or modify the configuration options of the widget. If one or more \fIoption\-value\fR pairs are specified, then the command modifies the given widget option(s) to have the given value(s); in this case the command returns an empty string. @@ -193,29 +191,27 @@ .\" Note: Ttk widgets don't use TK_OPTION_SYNONYM. If no \fIoption\fR is specified, returns a list describing all of the available options for \fIpathName\fR. .TP \fIpathName \fBidentify element \fIx y\fR -. Returns the name of the element under the point given by \fIx\fR and \fIy\fR, or an empty string if the point does not lie within any element. \fIx\fR and \fIy\fR are pixel coordinates relative to the widget. -Some widgets accept other \fBidentify\fR subcommands. +Some widgets accept other \fBidentify\fR subcommands described +in these widgets documentation. .TP \fIpathName \fBinstate \fIstatespec\fR ?\fIscript\fR? -. Test the widget's state. If \fIscript\fR is not specified, returns 1 if the widget state matches \fIstatespec\fR and 0 otherwise. If \fIscript\fR is specified, equivalent to .CS if {[\fIpathName\fR instate \fIstateSpec\fR]} \fIscript\fR .CE .TP \fIpathName \fBstate\fR ?\fIstateSpec\fR? -. Modify or inquire widget state. If \fIstateSpec\fR is present, sets the widget state: for each flag in \fIstateSpec\fR, sets the corresponding flag or clears it if prefixed by an exclamation point. .RS @@ -227,10 +223,13 @@ will restore \fIpathName\fR to the original state. If \fIstateSpec\fR is not specified, returns a list of the currently-enabled state flags. .RE .TP +\fIpathName \fBstyle\fR +Return the style used by the widget. +.TP \fIpathName \fBxview \fIargs\fR This command is used to query and change the horizontal position of the content in the widget's window. It can take any of the following forms: .RS Index: doc/wm.n ================================================================== --- doc/wm.n +++ doc/wm.n @@ -118,11 +118,11 @@ color with some alpha, e.g. .QW systemTransparent . .PP On X11, the following attributes may be set. These are not supported by all window managers, and will have no effect under older WMs. -.\" See http://www.freedesktop.org/Standards/wm-spec +.\" See https://www.freedesktop.org/wiki/Specifications/wm-spec/ .TP \fB\-type\fR .VS 8.6 Requests that the window should be interpreted by the window manager as being of the specified type(s). This may cause the window to be decorated in a @@ -404,10 +404,41 @@ leader is iconified. \fIPathName\fR may be specified as an empty string to remove \fIwindow\fR from any group association. If \fIpathName\fR is specified then the command returns an empty string; otherwise it returns the path name of \fIwindow\fR's current group leader, or an empty string if \fIwindow\fR is not part of any group. +.TP +\fBwm iconbadge \fIwindow\fR \fIbadge\fR +. +Sets a badge for the icon of the \fIwindow\fR. The badge can be a positive +integer number, for instance the number of new or unread messages, or +an exclamation point denoting attention needed. If the badge is an empty +string, the badge image is removed from the application icon. Managing +these changes through bindings, such as , is the responsibility +of the developer. +.RS +.PP +On X11, for this command to work, +the variable \fB::tk::icons::base_icon($window)\fR must be set to the image that is +being used for the window icon of $window. On Windows and X11, the iconphoto +images work best at 32x32 or a similar dimension, as +the badge images are provided by Tk and drawn to overlay the icon images +using native (Windows) API's or Tk rendering. On macOS, the icon badge is +rendered by a system API and is not provided by Tk. The icon image itself +should be higher-resolution, preferably 512 pixels, to avoid being blurry. +.PP +The icon badge is intended for display in the Dock (macOS), taskbar +(Windows) or app panel (X11). On macOS, the last badge called will be +displayed in the Dock, regardless of how many different icon badges may be +assigned to different windows. On Windows, the taskbar display depends on +whether the taskbar buttons are combined or not (this is an OS setting +available to the user): if combined the behavior is the same as on macOS, +otherwise each button in the taskbar shows the badge it was assigned. +Badge display on macOS is configured in the system preferences. App +panel display behavior on X11 will depend on the window manager and/or +desktop environment. +.RE .TP \fBwm iconbitmap \fIwindow\fR ?\fIbitmap\fR? . If \fIbitmap\fR is specified, then it names a bitmap in the standard forms accepted by Tk (see the \fBTk_GetBitmap\fR manual entry for details). @@ -479,16 +510,17 @@ manager may scale provided icons to an appropriate size. .RS .PP On Windows, the images are packed into a Windows icon structure. This will override an ico specified to \fBwm iconbitmap\fR, and -vice versa. +vice versa. This command sets the taskbar icon for the window. .PP On X, the images are arranged into the _NET_WM_ICON X property, which most modern window managers support. A \fBwm iconbitmap\fR may exist simultaneously. It is recommended to use not more than 2 icons, placing -the larger icon first. +the larger icon first. This command also sets the panel icon for the +application if the window manager or desktop environment supports it. .PP On Macintosh, the first image called is loaded into an OSX-native icon format, and becomes the application icon in dialogs, the Dock, and other contexts. At the script level the command will accept only the first image passed in the Index: generic/ks_names.h ================================================================== --- generic/ks_names.h +++ generic/ks_names.h @@ -18,16 +18,11 @@ { "Return", 0xFF0D }, { "Pause", 0xFF13 }, { "Scroll_Lock", 0xFF14 }, { "Sys_Req", 0xFF15 }, { "Escape", 0xFF1B }, -{ "Delete", 0xFFFF }, { "Multi_key", 0xFF20 }, -{ "Codeinput", 0xFF37 }, -{ "SingleCandidate", 0xFF3C }, -{ "MultipleCandidate", 0xFF3D }, -{ "PreviousCandidate", 0xFF3E }, { "Kanji", 0xFF21 }, { "Muhenkan", 0xFF22 }, { "Henkan_Mode", 0xFF23 }, { "Henkan", 0xFF23 }, { "Romaji", 0xFF24 }, @@ -41,13 +36,25 @@ { "Massyo", 0xFF2C }, { "Kana_Lock", 0xFF2D }, { "Kana_Shift", 0xFF2E }, { "Eisu_Shift", 0xFF2F }, { "Eisu_toggle", 0xFF30 }, -{ "Kanji_Bangou", 0xFF37 }, -{ "Zen_Koho", 0xFF3D }, -{ "Mae_Koho", 0xFF3E }, +{ "Hangul", 0xFF31 }, +{ "Hangul_Start", 0xFF32 }, +{ "Hangul_End", 0xFF33 }, +{ "Hangul_Hanja", 0xFF34 }, +{ "Hangul_Jamo", 0xFF35 }, +{ "Hangul_Romaja", 0xFF36 }, +{ "Codeinput", 0xFF37 }, +{ "Hangul_Jeonja", 0xFF38 }, +{ "Hangul_Banja", 0xFF39 }, +{ "Hangul_PreHanja", 0xFF3A }, +{ "Hangul_PostHanja", 0xFF3B }, +{ "SingleCandidate", 0xFF3C }, +{ "MultipleCandidate", 0xFF3D }, +{ "PreviousCandidate", 0xFF3E }, +{ "Hangul_Special", 0xFF3F }, { "Home", 0xFF50 }, { "Left", 0xFF51 }, { "Up", 0xFF52 }, { "Right", 0xFF53 }, { "Down", 0xFF54 }, @@ -55,26 +62,32 @@ { "Page_Up", 0xFF55 }, { "Next", 0xFF56 }, { "Page_Down", 0xFF56 }, { "End", 0xFF57 }, { "Begin", 0xFF58 }, -{ "Win_L", 0xFF5B }, -{ "Win_R", 0xFF5C }, -{ "App", 0xFF5D }, { "Select", 0xFF60 }, { "Print", 0xFF61 }, { "Execute", 0xFF62 }, { "Insert", 0xFF63 }, { "Undo", 0xFF65 }, { "Redo", 0xFF66 }, { "Menu", 0xFF67 }, +#ifndef TK_NO_DEPRECATED +{ "App", 0xFF67 }, +#endif { "Find", 0xFF68 }, { "Cancel", 0xFF69 }, { "Help", 0xFF6A }, { "Break", 0xFF6B }, { "Mode_switch", 0xFF7E }, +#ifndef TK_NO_DEPRECATED { "script_switch", 0xFF7E }, +{ "kana_switch", 0xFF7E }, +{ "Arabic_switch", 0xFF7E }, +{ "Greek_switch", 0xFF7E }, +{ "Hebrew_switch", 0xFF7E }, +#endif { "Num_Lock", 0xFF7F }, { "KP_Space", 0xFF80 }, { "KP_Tab", 0xFF89 }, { "KP_Enter", 0xFF8D }, { "KP_F1", 0xFF91 }, @@ -92,11 +105,10 @@ { "KP_Page_Down", 0xFF9B }, { "KP_End", 0xFF9C }, { "KP_Begin", 0xFF9D }, { "KP_Insert", 0xFF9E }, { "KP_Delete", 0xFF9F }, -{ "KP_Equal", 0xFFBD }, { "KP_Multiply", 0xFFAA }, { "KP_Add", 0xFFAB }, { "KP_Separator", 0xFFAC }, { "KP_Subtract", 0xFFAD }, { "KP_Decimal", 0xFFAE }, @@ -109,10 +121,11 @@ { "KP_5", 0xFFB5 }, { "KP_6", 0xFFB6 }, { "KP_7", 0xFFB7 }, { "KP_8", 0xFFB8 }, { "KP_9", 0xFFB9 }, +{ "KP_Equal", 0xFFBD }, { "F1", 0xFFBE }, { "F2", 0xFFBF }, { "F3", 0xFFC0 }, { "F4", 0xFFC1 }, { "F5", 0xFFC2 }, @@ -180,22 +193,35 @@ { "Meta_L", 0xFFE7 }, { "Meta_R", 0xFFE8 }, { "Alt_L", 0xFFE9 }, { "Alt_R", 0xFFEA }, { "Super_L", 0xFFEB }, +#ifndef TK_NO_DEPRECATED +{ "Win_L", 0xFFEB }, +#endif { "Super_R", 0xFFEC }, +#ifndef TK_NO_DEPRECATED +{ "Win_R", 0xFFEC }, +#endif { "Hyper_L", 0xFFED }, { "Hyper_R", 0xFFEE }, +{ "braille_dot_1", 0xFFF1 }, +{ "braille_dot_2", 0xFFF2 }, +{ "braille_dot_3", 0xFFF3 }, +{ "braille_dot_4", 0xFFF4 }, +{ "braille_dot_5", 0xFFF5 }, +{ "braille_dot_6", 0xFFF6 }, +{ "braille_dot_7", 0xFFF7 }, +{ "braille_dot_8", 0xFFF8 }, +{ "braille_dot_9", 0xFFF9 }, +{ "braille_dot_10", 0xFFFA }, +{ "Delete", 0xFFFF }, { "ISO_Lock", 0xFE01 }, { "ISO_Level2_Latch", 0xFE02 }, { "ISO_Level3_Shift", 0xFE03 }, { "ISO_Level3_Latch", 0xFE04 }, { "ISO_Level3_Lock", 0xFE05 }, -{ "ISO_Level5_Shift", 0xFE11 }, -{ "ISO_Level5_Latch", 0xFE12 }, -{ "ISO_Level5_Lock", 0xFE13 }, -{ "ISO_Group_Shift", 0xFF7E }, { "ISO_Group_Latch", 0xFE06 }, { "ISO_Group_Lock", 0xFE07 }, { "ISO_Next_Group", 0xFE08 }, { "ISO_Next_Group_Lock", 0xFE09 }, { "ISO_Prev_Group", 0xFE0A }, @@ -202,10 +228,13 @@ { "ISO_Prev_Group_Lock", 0xFE0B }, { "ISO_First_Group", 0xFE0C }, { "ISO_First_Group_Lock", 0xFE0D }, { "ISO_Last_Group", 0xFE0E }, { "ISO_Last_Group_Lock", 0xFE0F }, +{ "ISO_Level5_Shift", 0xFE11 }, +{ "ISO_Level5_Latch", 0xFE12 }, +{ "ISO_Level5_Lock", 0xFE13 }, { "ISO_Left_Tab", 0xFE20 }, { "ISO_Move_Line_Up", 0xFE21 }, { "ISO_Move_Line_Down", 0xFE22 }, { "ISO_Partial_Line_Up", 0xFE23 }, { "ISO_Partial_Line_Down", 0xFE24 }, @@ -258,14 +287,21 @@ { "dead_belowbreve", 0xFE6B }, { "dead_belowdiaeresis", 0xFE6C }, { "dead_invertedbreve", 0xFE6D }, { "dead_belowcomma", 0xFE6E }, { "dead_currency", 0xFE6F }, -{ "dead_lowline", 0xFE90 }, -{ "dead_aboveverticalline", 0xFE91 }, -{ "dead_belowverticalline", 0xFE92 }, -{ "dead_longsolidusoverlay", 0xFE93 }, +{ "AccessX_Enable", 0xFE70 }, +{ "AccessX_Feedback_Enable", 0xFE71 }, +{ "RepeatKeys_Enable", 0xFE72 }, +{ "SlowKeys_Enable", 0xFE73 }, +{ "BounceKeys_Enable", 0xFE74 }, +{ "StickyKeys_Enable", 0xFE75 }, +{ "MouseKeys_Enable", 0xFE76 }, +{ "MouseKeys_Accel_Enable", 0xFE77 }, +{ "Overlay1_Enable", 0xFE78 }, +{ "Overlay2_Enable", 0xFE79 }, +{ "AudibleBell_Enable", 0xFE7A }, { "dead_a", 0xFE80 }, { "dead_A", 0xFE81 }, { "dead_e", 0xFE82 }, { "dead_E", 0xFE83 }, { "dead_i", 0xFE84 }, @@ -275,26 +311,25 @@ { "dead_u", 0xFE88 }, { "dead_U", 0xFE89 }, { "dead_small_schwa", 0xFE8A }, { "dead_capital_schwa", 0xFE8B }, { "dead_greek", 0xFE8C }, +{ "dead_lowline", 0xFE90 }, +{ "dead_aboveverticalline", 0xFE91 }, +{ "dead_belowverticalline", 0xFE92 }, +{ "dead_longsolidusoverlay", 0xFE93 }, +{ "ch", 0xFEA0 }, +{ "Ch", 0xFEA1 }, +{ "CH", 0xFEA2 }, +{ "c_h", 0xFEA3 }, +{ "C_h", 0xFEA4 }, +{ "C_H", 0xFEA5 }, { "First_Virtual_Screen", 0xFED0 }, { "Prev_Virtual_Screen", 0xFED1 }, { "Next_Virtual_Screen", 0xFED2 }, { "Last_Virtual_Screen", 0xFED4 }, { "Terminate_Server", 0xFED5 }, -{ "AccessX_Enable", 0xFE70 }, -{ "AccessX_Feedback_Enable", 0xFE71 }, -{ "RepeatKeys_Enable", 0xFE72 }, -{ "SlowKeys_Enable", 0xFE73 }, -{ "BounceKeys_Enable", 0xFE74 }, -{ "StickyKeys_Enable", 0xFE75 }, -{ "MouseKeys_Enable", 0xFE76 }, -{ "MouseKeys_Accel_Enable", 0xFE77 }, -{ "Overlay1_Enable", 0xFE78 }, -{ "Overlay2_Enable", 0xFE79 }, -{ "AudibleBell_Enable", 0xFE7A }, { "Pointer_Left", 0xFEE0 }, { "Pointer_Right", 0xFEE1 }, { "Pointer_Up", 0xFEE2 }, { "Pointer_Down", 0xFEE3 }, { "Pointer_UpLeft", 0xFEE4 }, @@ -316,21 +351,15 @@ { "Pointer_Drag_Dflt", 0xFEF4 }, { "Pointer_Drag1", 0xFEF5 }, { "Pointer_Drag2", 0xFEF6 }, { "Pointer_Drag3", 0xFEF7 }, { "Pointer_Drag4", 0xFEF8 }, -{ "Pointer_Drag5", 0xFEFD }, { "Pointer_EnableKeys", 0xFEF9 }, { "Pointer_Accelerate", 0xFEFA }, { "Pointer_DfltBtnNext", 0xFEFB }, { "Pointer_DfltBtnPrev", 0xFEFC }, -{ "ch", 0xFEA0 }, -{ "Ch", 0xFEA1 }, -{ "CH", 0xFEA2 }, -{ "c_h", 0xFEA3 }, -{ "C_h", 0xFEA4 }, -{ "C_H", 0xFEA5 }, +{ "Pointer_Drag5", 0xFEFD }, { "3270_Duplicate", 0xFD01 }, { "3270_FieldMark", 0xFD02 }, { "3270_Right2", 0xFD03 }, { "3270_Left2", 0xFD04 }, { "3270_BackTab", 0xFD05 }, @@ -358,24 +387,29 @@ { "3270_ExSelect", 0xFD1B }, { "3270_CursorSelect", 0xFD1C }, { "3270_PrintScreen", 0xFD1D }, { "3270_Enter", 0xFD1E }, { "space", 0x20 }, +#ifndef TK_NO_DEPRECATED { "exclam", 0x21 }, +#endif { "quotedbl", 0x22 }, { "numbersign", 0x23 }, { "dollar", 0x24 }, +#ifndef TK_NO_DEPRECATED { "percent", 0x25 }, { "ampersand", 0x26 }, { "apostrophe", 0x27 }, { "quoteright", 0x27 }, { "parenleft", 0x28 }, { "parenright", 0x29 }, { "asterisk", 0x2A }, { "plus", 0x2B }, { "comma", 0x2C }, +#endif { "minus", 0x2D }, +#ifndef TK_NO_DEPRECATED { "period", 0x2E }, { "slash", 0x2F }, { "0", 0x30 }, { "1", 0x31 }, { "2", 0x32 }, @@ -385,14 +419,18 @@ { "6", 0x36 }, { "7", 0x37 }, { "8", 0x38 }, { "9", 0x39 }, { "colon", 0x3A }, +#endif { "semicolon", 0x3B }, { "less", 0x3C }, +#ifndef TK_NO_DEPRECATED { "equal", 0x3D }, +#endif { "greater", 0x3E }, +#ifndef TK_NO_DEPRECATED { "question", 0x3F }, { "at", 0x40 }, { "A", 0x41 }, { "B", 0x42 }, { "C", 0x43 }, @@ -417,13 +455,15 @@ { "V", 0x56 }, { "W", 0x57 }, { "X", 0x58 }, { "Y", 0x59 }, { "Z", 0x5A }, +#endif { "bracketleft", 0x5B }, { "backslash", 0x5C }, { "bracketright", 0x5D }, +#ifndef TK_NO_DEPRECATED { "asciicircum", 0x5E }, { "underscore", 0x5F }, { "grave", 0x60 }, { "quoteleft", 0x60 }, { "a", 0x61 }, @@ -450,15 +490,21 @@ { "v", 0x76 }, { "w", 0x77 }, { "x", 0x78 }, { "y", 0x79 }, { "z", 0x7A }, +#endif { "braceleft", 0x7B }, +#ifndef TK_NO_DEPRECATED { "bar", 0x7C }, +#endif { "braceright", 0x7D }, +#ifndef TK_NO_DEPRECATED { "asciitilde", 0x7E }, +#endif { "nobreakspace", 0xA0 }, +#ifndef TK_NO_DEPRECATED { "exclamdown", 0xA1 }, { "cent", 0xA2 }, { "sterling", 0xA3 }, { "currency", 0xA4 }, { "yen", 0xA5 }, @@ -548,20 +594,18 @@ { "ocircumflex", 0xF4 }, { "otilde", 0xF5 }, { "odiaeresis", 0xF6 }, { "division", 0xF7 }, { "oslash", 0xF8 }, -#ifndef TK_NO_DEPRECATED -{ "ooblique", 0xF8 }, -#endif { "ugrave", 0xF9 }, { "uacute", 0xFA }, { "ucircumflex", 0xFB }, { "udiaeresis", 0xFC }, { "yacute", 0xFD }, { "thorn", 0xFE }, { "ydiaeresis", 0xFF }, +#endif /* TK_NO_DEPRECATED */ { "Aogonek", 0x1A1 }, { "breve", 0x1A2 }, { "Lstroke", 0x1A3 }, { "Lcaron", 0x1A5 }, { "Sacute", 0x1A6 }, @@ -678,36 +722,10 @@ { "omacron", 0x3F2 }, { "kcedilla", 0x3F3 }, { "uogonek", 0x3F9 }, { "utilde", 0x3FD }, { "umacron", 0x3FE }, -{ "Wcircumflex", 0x1000174 }, -{ "wcircumflex", 0x1000175 }, -{ "Ycircumflex", 0x1000176 }, -{ "ycircumflex", 0x1000177 }, -{ "Babovedot", 0x1001E02 }, -{ "babovedot", 0x1001E03 }, -{ "Dabovedot", 0x1001E0A }, -{ "dabovedot", 0x1001E0B }, -{ "Fabovedot", 0x1001E1E }, -{ "fabovedot", 0x1001E1F }, -{ "Mabovedot", 0x1001E40 }, -{ "mabovedot", 0x1001E41 }, -{ "Pabovedot", 0x1001E56 }, -{ "pabovedot", 0x1001E57 }, -{ "Sabovedot", 0x1001E60 }, -{ "sabovedot", 0x1001E61 }, -{ "Tabovedot", 0x1001E6A }, -{ "tabovedot", 0x1001E6B }, -{ "Wgrave", 0x1001E80 }, -{ "wgrave", 0x1001E81 }, -{ "Wacute", 0x1001E82 }, -{ "wacute", 0x1001E83 }, -{ "Wdiaeresis", 0x1001E84 }, -{ "wdiaeresis", 0x1001E85 }, -{ "Ygrave", 0x1001EF2 }, -{ "ygrave", 0x1001EF3 }, { "OE", 0x13BC }, { "oe", 0x13BD }, { "Ydiaeresis", 0x13BE }, { "overline", 0x47E }, { "kana_fullstop", 0x4A1 }, @@ -786,40 +804,11 @@ { "kana_RO", 0x4DB }, { "kana_WA", 0x4DC }, { "kana_N", 0x4DD }, { "voicedsound", 0x4DE }, { "semivoicedsound", 0x4DF }, -{ "kana_switch", 0xFF7E }, -{ "Farsi_0", 0x10006F0 }, -{ "Farsi_1", 0x10006F1 }, -{ "Farsi_2", 0x10006F2 }, -{ "Farsi_3", 0x10006F3 }, -{ "Farsi_4", 0x10006F4 }, -{ "Farsi_5", 0x10006F5 }, -{ "Farsi_6", 0x10006F6 }, -{ "Farsi_7", 0x10006F7 }, -{ "Farsi_8", 0x10006F8 }, -{ "Farsi_9", 0x10006F9 }, -{ "Arabic_percent", 0x100066A }, -{ "Arabic_superscript_alef", 0x1000670 }, -{ "Arabic_tteh", 0x1000679 }, -{ "Arabic_peh", 0x100067E }, -{ "Arabic_tcheh", 0x1000686 }, -{ "Arabic_ddal", 0x1000688 }, -{ "Arabic_rreh", 0x1000691 }, { "Arabic_comma", 0x5AC }, -{ "Arabic_fullstop", 0x10006D4 }, -{ "Arabic_0", 0x1000660 }, -{ "Arabic_1", 0x1000661 }, -{ "Arabic_2", 0x1000662 }, -{ "Arabic_3", 0x1000663 }, -{ "Arabic_4", 0x1000664 }, -{ "Arabic_5", 0x1000665 }, -{ "Arabic_6", 0x1000666 }, -{ "Arabic_7", 0x1000667 }, -{ "Arabic_8", 0x1000668 }, -{ "Arabic_9", 0x1000669 }, { "Arabic_semicolon", 0x5BB }, { "Arabic_question_mark", 0x5BF }, { "Arabic_hamza", 0x5C1 }, { "Arabic_maddaonalef", 0x5C2 }, { "Arabic_hamzaonalef", 0x5C3 }, @@ -866,54 +855,10 @@ { "Arabic_fatha", 0x5EE }, { "Arabic_damma", 0x5EF }, { "Arabic_kasra", 0x5F0 }, { "Arabic_shadda", 0x5F1 }, { "Arabic_sukun", 0x5F2 }, -{ "Arabic_madda_above", 0x1000653 }, -{ "Arabic_hamza_above", 0x1000654 }, -{ "Arabic_hamza_below", 0x1000655 }, -{ "Arabic_jeh", 0x1000698 }, -{ "Arabic_veh", 0x10006A4 }, -{ "Arabic_keheh", 0x10006A9 }, -{ "Arabic_gaf", 0x10006AF }, -{ "Arabic_noon_ghunna", 0x10006BA }, -{ "Arabic_heh_doachashmee", 0x10006BE }, -{ "Farsi_yeh", 0x10006CC }, -{ "Arabic_farsi_yeh", 0x10006CC }, -{ "Arabic_yeh_baree", 0x10006D2 }, -{ "Arabic_heh_goal", 0x10006C1 }, -{ "Arabic_switch", 0xFF7E }, -{ "Cyrillic_GHE_bar", 0x1000492 }, -{ "Cyrillic_ghe_bar", 0x1000493 }, -{ "Cyrillic_ZHE_descender", 0x1000496 }, -{ "Cyrillic_zhe_descender", 0x1000497 }, -{ "Cyrillic_KA_descender", 0x100049A }, -{ "Cyrillic_ka_descender", 0x100049B }, -{ "Cyrillic_KA_vertstroke", 0x100049C }, -{ "Cyrillic_ka_vertstroke", 0x100049D }, -{ "Cyrillic_EN_descender", 0x10004A2 }, -{ "Cyrillic_en_descender", 0x10004A3 }, -{ "Cyrillic_U_straight", 0x10004AE }, -{ "Cyrillic_u_straight", 0x10004AF }, -{ "Cyrillic_U_straight_bar", 0x10004B0 }, -{ "Cyrillic_u_straight_bar", 0x10004B1 }, -{ "Cyrillic_HA_descender", 0x10004B2 }, -{ "Cyrillic_ha_descender", 0x10004B3 }, -{ "Cyrillic_CHE_descender", 0x10004B6 }, -{ "Cyrillic_che_descender", 0x10004B7 }, -{ "Cyrillic_CHE_vertstroke", 0x10004B8 }, -{ "Cyrillic_che_vertstroke", 0x10004B9 }, -{ "Cyrillic_SHHA", 0x10004BA }, -{ "Cyrillic_shha", 0x10004BB }, -{ "Cyrillic_SCHWA", 0x10004D8 }, -{ "Cyrillic_schwa", 0x10004D9 }, -{ "Cyrillic_I_macron", 0x10004E2 }, -{ "Cyrillic_i_macron", 0x10004E3 }, -{ "Cyrillic_O_bar", 0x10004E8 }, -{ "Cyrillic_o_bar", 0x10004E9 }, -{ "Cyrillic_U_macron", 0x10004EE }, -{ "Cyrillic_u_macron", 0x10004EF }, { "Serbian_dje", 0x6A1 }, { "Macedonia_gje", 0x6A2 }, { "Cyrillic_io", 0x6A3 }, { "Ukrainian_ie", 0x6A4 }, #ifndef TK_NO_DEPRECATED @@ -1052,11 +997,13 @@ { "Greek_ALPHAaccent", 0x7A1 }, { "Greek_EPSILONaccent", 0x7A2 }, { "Greek_ETAaccent", 0x7A3 }, { "Greek_IOTAaccent", 0x7A4 }, { "Greek_IOTAdieresis", 0x7A5 }, +#ifndef TK_NO_DEPRECATED { "Greek_IOTAdiaeresis", 0x7A5 }, +#endif { "Greek_IOTAaccentdiaeresis", 0x7A6 }, { "Greek_OMICRONaccent", 0x7A7 }, { "Greek_UPSILONaccent", 0x7A8 }, { "Greek_UPSILONdieresis", 0x7A9 }, { "Greek_UPSILONaccentdieresis", 0x7AA }, @@ -1123,11 +1070,10 @@ { "Greek_upsilon", 0x7F5 }, { "Greek_phi", 0x7F6 }, { "Greek_chi", 0x7F7 }, { "Greek_psi", 0x7F8 }, { "Greek_omega", 0x7F9 }, -{ "Greek_switch", 0xFF7E }, { "leftradical", 0x8A1 }, { "topleftradical", 0x8A2 }, { "horizconnector", 0x8A3 }, { "topintegral", 0x8A4 }, { "botintegral", 0x8A5 }, @@ -1361,11 +1307,10 @@ { "hebrew_shin", 0xCF9 }, { "hebrew_taw", 0xCFA }, #ifndef TK_NO_DEPRECATED { "hebrew_taf", 0xCFA }, #endif -{ "Hebrew_switch", 0xFF7E }, { "Thai_kokai", 0xDA1 }, { "Thai_khokhai", 0xDA2 }, { "Thai_khokhuat", 0xDA3 }, { "Thai_khokhwai", 0xDA4 }, { "Thai_khokhon", 0xDA5 }, @@ -1446,26 +1391,10 @@ { "Thai_lekha", 0xDF5 }, { "Thai_lekhok", 0xDF6 }, { "Thai_lekchet", 0xDF7 }, { "Thai_lekpaet", 0xDF8 }, { "Thai_lekkao", 0xDF9 }, -{ "Hangul", 0xFF31 }, -{ "Hangul_Start", 0xFF32 }, -{ "Hangul_End", 0xFF33 }, -{ "Hangul_Hanja", 0xFF34 }, -{ "Hangul_Jamo", 0xFF35 }, -{ "Hangul_Romaja", 0xFF36 }, -{ "Hangul_Codeinput", 0xFF37 }, -{ "Hangul_Jeonja", 0xFF38 }, -{ "Hangul_Banja", 0xFF39 }, -{ "Hangul_PreHanja", 0xFF3A }, -{ "Hangul_PostHanja", 0xFF3B }, -{ "Hangul_SingleCandidate", 0xFF3C }, -{ "Hangul_MultipleCandidate", 0xFF3D }, -{ "Hangul_PreviousCandidate", 0xFF3E }, -{ "Hangul_Special", 0xFF3F }, -{ "Hangul_switch", 0xFF7E }, { "Hangul_Kiyeog", 0xEA1 }, { "Hangul_SsangKiyeog", 0xEA2 }, { "Hangul_KiyeogSios", 0xEA3 }, { "Hangul_Nieun", 0xEA4 }, { "Hangul_NieunJieuj", 0xEA5 }, @@ -1553,640 +1482,10 @@ { "Hangul_AraeAE", 0xEF7 }, { "Hangul_J_PanSios", 0xEF8 }, { "Hangul_J_KkogjiDalrinIeung", 0xEF9 }, { "Hangul_J_YeorinHieuh", 0xEFA }, { "Korean_Won", 0xEFF }, -{ "Armenian_ligature_ew", 0x1000587 }, -{ "Armenian_full_stop", 0x1000589 }, -{ "Armenian_verjaket", 0x1000589 }, -{ "Armenian_separation_mark", 0x100055D }, -{ "Armenian_but", 0x100055D }, -{ "Armenian_hyphen", 0x100058A }, -{ "Armenian_yentamna", 0x100058A }, -{ "Armenian_exclam", 0x100055C }, -{ "Armenian_amanak", 0x100055C }, -{ "Armenian_accent", 0x100055B }, -{ "Armenian_shesht", 0x100055B }, -{ "Armenian_question", 0x100055E }, -{ "Armenian_paruyk", 0x100055E }, -{ "Armenian_AYB", 0x1000531 }, -{ "Armenian_ayb", 0x1000561 }, -{ "Armenian_BEN", 0x1000532 }, -{ "Armenian_ben", 0x1000562 }, -{ "Armenian_GIM", 0x1000533 }, -{ "Armenian_gim", 0x1000563 }, -{ "Armenian_DA", 0x1000534 }, -{ "Armenian_da", 0x1000564 }, -{ "Armenian_YECH", 0x1000535 }, -{ "Armenian_yech", 0x1000565 }, -{ "Armenian_ZA", 0x1000536 }, -{ "Armenian_za", 0x1000566 }, -{ "Armenian_E", 0x1000537 }, -{ "Armenian_e", 0x1000567 }, -{ "Armenian_AT", 0x1000538 }, -{ "Armenian_at", 0x1000568 }, -{ "Armenian_TO", 0x1000539 }, -{ "Armenian_to", 0x1000569 }, -{ "Armenian_ZHE", 0x100053A }, -{ "Armenian_zhe", 0x100056A }, -{ "Armenian_INI", 0x100053B }, -{ "Armenian_ini", 0x100056B }, -{ "Armenian_LYUN", 0x100053C }, -{ "Armenian_lyun", 0x100056C }, -{ "Armenian_KHE", 0x100053D }, -{ "Armenian_khe", 0x100056D }, -{ "Armenian_TSA", 0x100053E }, -{ "Armenian_tsa", 0x100056E }, -{ "Armenian_KEN", 0x100053F }, -{ "Armenian_ken", 0x100056F }, -{ "Armenian_HO", 0x1000540 }, -{ "Armenian_ho", 0x1000570 }, -{ "Armenian_DZA", 0x1000541 }, -{ "Armenian_dza", 0x1000571 }, -{ "Armenian_GHAT", 0x1000542 }, -{ "Armenian_ghat", 0x1000572 }, -{ "Armenian_TCHE", 0x1000543 }, -{ "Armenian_tche", 0x1000573 }, -{ "Armenian_MEN", 0x1000544 }, -{ "Armenian_men", 0x1000574 }, -{ "Armenian_HI", 0x1000545 }, -{ "Armenian_hi", 0x1000575 }, -{ "Armenian_NU", 0x1000546 }, -{ "Armenian_nu", 0x1000576 }, -{ "Armenian_SHA", 0x1000547 }, -{ "Armenian_sha", 0x1000577 }, -{ "Armenian_VO", 0x1000548 }, -{ "Armenian_vo", 0x1000578 }, -{ "Armenian_CHA", 0x1000549 }, -{ "Armenian_cha", 0x1000579 }, -{ "Armenian_PE", 0x100054A }, -{ "Armenian_pe", 0x100057A }, -{ "Armenian_JE", 0x100054B }, -{ "Armenian_je", 0x100057B }, -{ "Armenian_RA", 0x100054C }, -{ "Armenian_ra", 0x100057C }, -{ "Armenian_SE", 0x100054D }, -{ "Armenian_se", 0x100057D }, -{ "Armenian_VEV", 0x100054E }, -{ "Armenian_vev", 0x100057E }, -{ "Armenian_TYUN", 0x100054F }, -{ "Armenian_tyun", 0x100057F }, -{ "Armenian_RE", 0x1000550 }, -{ "Armenian_re", 0x1000580 }, -{ "Armenian_TSO", 0x1000551 }, -{ "Armenian_tso", 0x1000581 }, -{ "Armenian_VYUN", 0x1000552 }, -{ "Armenian_vyun", 0x1000582 }, -{ "Armenian_PYUR", 0x1000553 }, -{ "Armenian_pyur", 0x1000583 }, -{ "Armenian_KE", 0x1000554 }, -{ "Armenian_ke", 0x1000584 }, -{ "Armenian_O", 0x1000555 }, -{ "Armenian_o", 0x1000585 }, -{ "Armenian_FE", 0x1000556 }, -{ "Armenian_fe", 0x1000586 }, -{ "Armenian_apostrophe", 0x100055A }, -{ "Georgian_an", 0x10010D0 }, -{ "Georgian_ban", 0x10010D1 }, -{ "Georgian_gan", 0x10010D2 }, -{ "Georgian_don", 0x10010D3 }, -{ "Georgian_en", 0x10010D4 }, -{ "Georgian_vin", 0x10010D5 }, -{ "Georgian_zen", 0x10010D6 }, -{ "Georgian_tan", 0x10010D7 }, -{ "Georgian_in", 0x10010D8 }, -{ "Georgian_kan", 0x10010D9 }, -{ "Georgian_las", 0x10010DA }, -{ "Georgian_man", 0x10010DB }, -{ "Georgian_nar", 0x10010DC }, -{ "Georgian_on", 0x10010DD }, -{ "Georgian_par", 0x10010DE }, -{ "Georgian_zhar", 0x10010DF }, -{ "Georgian_rae", 0x10010E0 }, -{ "Georgian_san", 0x10010E1 }, -{ "Georgian_tar", 0x10010E2 }, -{ "Georgian_un", 0x10010E3 }, -{ "Georgian_phar", 0x10010E4 }, -{ "Georgian_khar", 0x10010E5 }, -{ "Georgian_ghan", 0x10010E6 }, -{ "Georgian_qar", 0x10010E7 }, -{ "Georgian_shin", 0x10010E8 }, -{ "Georgian_chin", 0x10010E9 }, -{ "Georgian_can", 0x10010EA }, -{ "Georgian_jil", 0x10010EB }, -{ "Georgian_cil", 0x10010EC }, -{ "Georgian_char", 0x10010ED }, -{ "Georgian_xan", 0x10010EE }, -{ "Georgian_jhan", 0x10010EF }, -{ "Georgian_hae", 0x10010F0 }, -{ "Georgian_he", 0x10010F1 }, -{ "Georgian_hie", 0x10010F2 }, -{ "Georgian_we", 0x10010F3 }, -{ "Georgian_har", 0x10010F4 }, -{ "Georgian_hoe", 0x10010F5 }, -{ "Georgian_fi", 0x10010F6 }, -{ "Xabovedot", 0x1001E8A }, -{ "Ibreve", 0x100012C }, -{ "Zstroke", 0x10001B5 }, -{ "Gcaron", 0x10001E6 }, -{ "Ocaron", 0x10001D1 }, -{ "Obarred", 0x100019F }, -{ "xabovedot", 0x1001E8B }, -{ "ibreve", 0x100012D }, -{ "zstroke", 0x10001B6 }, -{ "gcaron", 0x10001E7 }, -{ "ocaron", 0x10001D2 }, -{ "obarred", 0x1000275 }, -{ "SCHWA", 0x100018F }, -{ "schwa", 0x1000259 }, -{ "EZH", 0x10001B7 }, -{ "ezh", 0x1000292 }, -{ "Lbelowdot", 0x1001E36 }, -{ "lbelowdot", 0x1001E37 }, -{ "Abelowdot", 0x1001EA0 }, -{ "abelowdot", 0x1001EA1 }, -{ "Ahook", 0x1001EA2 }, -{ "ahook", 0x1001EA3 }, -{ "Acircumflexacute", 0x1001EA4 }, -{ "acircumflexacute", 0x1001EA5 }, -{ "Acircumflexgrave", 0x1001EA6 }, -{ "acircumflexgrave", 0x1001EA7 }, -{ "Acircumflexhook", 0x1001EA8 }, -{ "acircumflexhook", 0x1001EA9 }, -{ "Acircumflextilde", 0x1001EAA }, -{ "acircumflextilde", 0x1001EAB }, -{ "Acircumflexbelowdot", 0x1001EAC }, -{ "acircumflexbelowdot", 0x1001EAD }, -{ "Abreveacute", 0x1001EAE }, -{ "abreveacute", 0x1001EAF }, -{ "Abrevegrave", 0x1001EB0 }, -{ "abrevegrave", 0x1001EB1 }, -{ "Abrevehook", 0x1001EB2 }, -{ "abrevehook", 0x1001EB3 }, -{ "Abrevetilde", 0x1001EB4 }, -{ "abrevetilde", 0x1001EB5 }, -{ "Abrevebelowdot", 0x1001EB6 }, -{ "abrevebelowdot", 0x1001EB7 }, -{ "Ebelowdot", 0x1001EB8 }, -{ "ebelowdot", 0x1001EB9 }, -{ "Ehook", 0x1001EBA }, -{ "ehook", 0x1001EBB }, -{ "Etilde", 0x1001EBC }, -{ "etilde", 0x1001EBD }, -{ "Ecircumflexacute", 0x1001EBE }, -{ "ecircumflexacute", 0x1001EBF }, -{ "Ecircumflexgrave", 0x1001EC0 }, -{ "ecircumflexgrave", 0x1001EC1 }, -{ "Ecircumflexhook", 0x1001EC2 }, -{ "ecircumflexhook", 0x1001EC3 }, -{ "Ecircumflextilde", 0x1001EC4 }, -{ "ecircumflextilde", 0x1001EC5 }, -{ "Ecircumflexbelowdot", 0x1001EC6 }, -{ "ecircumflexbelowdot", 0x1001EC7 }, -{ "Ihook", 0x1001EC8 }, -{ "ihook", 0x1001EC9 }, -{ "Ibelowdot", 0x1001ECA }, -{ "ibelowdot", 0x1001ECB }, -{ "Obelowdot", 0x1001ECC }, -{ "obelowdot", 0x1001ECD }, -{ "Ohook", 0x1001ECE }, -{ "ohook", 0x1001ECF }, -{ "Ocircumflexacute", 0x1001ED0 }, -{ "ocircumflexacute", 0x1001ED1 }, -{ "Ocircumflexgrave", 0x1001ED2 }, -{ "ocircumflexgrave", 0x1001ED3 }, -{ "Ocircumflexhook", 0x1001ED4 }, -{ "ocircumflexhook", 0x1001ED5 }, -{ "Ocircumflextilde", 0x1001ED6 }, -{ "ocircumflextilde", 0x1001ED7 }, -{ "Ocircumflexbelowdot", 0x1001ED8 }, -{ "ocircumflexbelowdot", 0x1001ED9 }, -{ "Ohornacute", 0x1001EDA }, -{ "ohornacute", 0x1001EDB }, -{ "Ohorngrave", 0x1001EDC }, -{ "ohorngrave", 0x1001EDD }, -{ "Ohornhook", 0x1001EDE }, -{ "ohornhook", 0x1001EDF }, -{ "Ohorntilde", 0x1001EE0 }, -{ "ohorntilde", 0x1001EE1 }, -{ "Ohornbelowdot", 0x1001EE2 }, -{ "ohornbelowdot", 0x1001EE3 }, -{ "Ubelowdot", 0x1001EE4 }, -{ "ubelowdot", 0x1001EE5 }, -{ "Uhook", 0x1001EE6 }, -{ "uhook", 0x1001EE7 }, -{ "Uhornacute", 0x1001EE8 }, -{ "uhornacute", 0x1001EE9 }, -{ "Uhorngrave", 0x1001EEA }, -{ "uhorngrave", 0x1001EEB }, -{ "Uhornhook", 0x1001EEC }, -{ "uhornhook", 0x1001EED }, -{ "Uhorntilde", 0x1001EEE }, -{ "uhorntilde", 0x1001EEF }, -{ "Uhornbelowdot", 0x1001EF0 }, -{ "uhornbelowdot", 0x1001EF1 }, -{ "Ybelowdot", 0x1001EF4 }, -{ "ybelowdot", 0x1001EF5 }, -{ "Yhook", 0x1001EF6 }, -{ "yhook", 0x1001EF7 }, -{ "Ytilde", 0x1001EF8 }, -{ "ytilde", 0x1001EF9 }, -{ "Ohorn", 0x10001A0 }, -{ "ohorn", 0x10001A1 }, -{ "Uhorn", 0x10001AF }, -{ "uhorn", 0x10001B0 }, -{ "EcuSign", 0x10020A0 }, -{ "ColonSign", 0x10020A1 }, -{ "CruzeiroSign", 0x10020A2 }, -{ "FFrancSign", 0x10020A3 }, -{ "LiraSign", 0x10020A4 }, -{ "MillSign", 0x10020A5 }, -{ "NairaSign", 0x10020A6 }, -{ "PesetaSign", 0x10020A7 }, -{ "RupeeSign", 0x10020A8 }, -{ "WonSign", 0x10020A9 }, -{ "NewSheqelSign", 0x10020AA }, -{ "DongSign", 0x10020AB }, -{ "EuroSign", 0x20AC }, -{ "zerosuperior", 0x1002070 }, -{ "foursuperior", 0x1002074 }, -{ "fivesuperior", 0x1002075 }, -{ "sixsuperior", 0x1002076 }, -{ "sevensuperior", 0x1002077 }, -{ "eightsuperior", 0x1002078 }, -{ "ninesuperior", 0x1002079 }, -{ "zerosubscript", 0x1002080 }, -{ "onesubscript", 0x1002081 }, -{ "twosubscript", 0x1002082 }, -{ "threesubscript", 0x1002083 }, -{ "foursubscript", 0x1002084 }, -{ "fivesubscript", 0x1002085 }, -{ "sixsubscript", 0x1002086 }, -{ "sevensubscript", 0x1002087 }, -{ "eightsubscript", 0x1002088 }, -{ "ninesubscript", 0x1002089 }, -{ "partdifferential", 0x1002202 }, -{ "emptyset", 0x1002205 }, -{ "elementof", 0x1002208 }, -{ "notelementof", 0x1002209 }, -{ "containsas", 0x100220B }, -{ "squareroot", 0x100221A }, -{ "cuberoot", 0x100221B }, -{ "fourthroot", 0x100221C }, -{ "dintegral", 0x100222C }, -{ "tintegral", 0x100222D }, -{ "because", 0x1002235 }, -{ "approxeq", 0x1002248 }, -{ "notapproxeq", 0x1002247 }, -{ "notidentical", 0x1002262 }, -{ "stricteq", 0x1002263 }, -{ "braille_dot_1", 0xFFF1 }, -{ "braille_dot_2", 0xFFF2 }, -{ "braille_dot_3", 0xFFF3 }, -{ "braille_dot_4", 0xFFF4 }, -{ "braille_dot_5", 0xFFF5 }, -{ "braille_dot_6", 0xFFF6 }, -{ "braille_dot_7", 0xFFF7 }, -{ "braille_dot_8", 0xFFF8 }, -{ "braille_dot_9", 0xFFF9 }, -{ "braille_dot_10", 0xFFFA }, -{ "braille_blank", 0x1002800 }, -{ "braille_dots_1", 0x1002801 }, -{ "braille_dots_2", 0x1002802 }, -{ "braille_dots_12", 0x1002803 }, -{ "braille_dots_3", 0x1002804 }, -{ "braille_dots_13", 0x1002805 }, -{ "braille_dots_23", 0x1002806 }, -{ "braille_dots_123", 0x1002807 }, -{ "braille_dots_4", 0x1002808 }, -{ "braille_dots_14", 0x1002809 }, -{ "braille_dots_24", 0x100280A }, -{ "braille_dots_124", 0x100280B }, -{ "braille_dots_34", 0x100280C }, -{ "braille_dots_134", 0x100280D }, -{ "braille_dots_234", 0x100280E }, -{ "braille_dots_1234", 0x100280F }, -{ "braille_dots_5", 0x1002810 }, -{ "braille_dots_15", 0x1002811 }, -{ "braille_dots_25", 0x1002812 }, -{ "braille_dots_125", 0x1002813 }, -{ "braille_dots_35", 0x1002814 }, -{ "braille_dots_135", 0x1002815 }, -{ "braille_dots_235", 0x1002816 }, -{ "braille_dots_1235", 0x1002817 }, -{ "braille_dots_45", 0x1002818 }, -{ "braille_dots_145", 0x1002819 }, -{ "braille_dots_245", 0x100281A }, -{ "braille_dots_1245", 0x100281B }, -{ "braille_dots_345", 0x100281C }, -{ "braille_dots_1345", 0x100281D }, -{ "braille_dots_2345", 0x100281E }, -{ "braille_dots_12345", 0x100281F }, -{ "braille_dots_6", 0x1002820 }, -{ "braille_dots_16", 0x1002821 }, -{ "braille_dots_26", 0x1002822 }, -{ "braille_dots_126", 0x1002823 }, -{ "braille_dots_36", 0x1002824 }, -{ "braille_dots_136", 0x1002825 }, -{ "braille_dots_236", 0x1002826 }, -{ "braille_dots_1236", 0x1002827 }, -{ "braille_dots_46", 0x1002828 }, -{ "braille_dots_146", 0x1002829 }, -{ "braille_dots_246", 0x100282A }, -{ "braille_dots_1246", 0x100282B }, -{ "braille_dots_346", 0x100282C }, -{ "braille_dots_1346", 0x100282D }, -{ "braille_dots_2346", 0x100282E }, -{ "braille_dots_12346", 0x100282F }, -{ "braille_dots_56", 0x1002830 }, -{ "braille_dots_156", 0x1002831 }, -{ "braille_dots_256", 0x1002832 }, -{ "braille_dots_1256", 0x1002833 }, -{ "braille_dots_356", 0x1002834 }, -{ "braille_dots_1356", 0x1002835 }, -{ "braille_dots_2356", 0x1002836 }, -{ "braille_dots_12356", 0x1002837 }, -{ "braille_dots_456", 0x1002838 }, -{ "braille_dots_1456", 0x1002839 }, -{ "braille_dots_2456", 0x100283A }, -{ "braille_dots_12456", 0x100283B }, -{ "braille_dots_3456", 0x100283C }, -{ "braille_dots_13456", 0x100283D }, -{ "braille_dots_23456", 0x100283E }, -{ "braille_dots_123456", 0x100283F }, -{ "braille_dots_7", 0x1002840 }, -{ "braille_dots_17", 0x1002841 }, -{ "braille_dots_27", 0x1002842 }, -{ "braille_dots_127", 0x1002843 }, -{ "braille_dots_37", 0x1002844 }, -{ "braille_dots_137", 0x1002845 }, -{ "braille_dots_237", 0x1002846 }, -{ "braille_dots_1237", 0x1002847 }, -{ "braille_dots_47", 0x1002848 }, -{ "braille_dots_147", 0x1002849 }, -{ "braille_dots_247", 0x100284A }, -{ "braille_dots_1247", 0x100284B }, -{ "braille_dots_347", 0x100284C }, -{ "braille_dots_1347", 0x100284D }, -{ "braille_dots_2347", 0x100284E }, -{ "braille_dots_12347", 0x100284F }, -{ "braille_dots_57", 0x1002850 }, -{ "braille_dots_157", 0x1002851 }, -{ "braille_dots_257", 0x1002852 }, -{ "braille_dots_1257", 0x1002853 }, -{ "braille_dots_357", 0x1002854 }, -{ "braille_dots_1357", 0x1002855 }, -{ "braille_dots_2357", 0x1002856 }, -{ "braille_dots_12357", 0x1002857 }, -{ "braille_dots_457", 0x1002858 }, -{ "braille_dots_1457", 0x1002859 }, -{ "braille_dots_2457", 0x100285A }, -{ "braille_dots_12457", 0x100285B }, -{ "braille_dots_3457", 0x100285C }, -{ "braille_dots_13457", 0x100285D }, -{ "braille_dots_23457", 0x100285E }, -{ "braille_dots_123457", 0x100285F }, -{ "braille_dots_67", 0x1002860 }, -{ "braille_dots_167", 0x1002861 }, -{ "braille_dots_267", 0x1002862 }, -{ "braille_dots_1267", 0x1002863 }, -{ "braille_dots_367", 0x1002864 }, -{ "braille_dots_1367", 0x1002865 }, -{ "braille_dots_2367", 0x1002866 }, -{ "braille_dots_12367", 0x1002867 }, -{ "braille_dots_467", 0x1002868 }, -{ "braille_dots_1467", 0x1002869 }, -{ "braille_dots_2467", 0x100286A }, -{ "braille_dots_12467", 0x100286B }, -{ "braille_dots_3467", 0x100286C }, -{ "braille_dots_13467", 0x100286D }, -{ "braille_dots_23467", 0x100286E }, -{ "braille_dots_123467", 0x100286F }, -{ "braille_dots_567", 0x1002870 }, -{ "braille_dots_1567", 0x1002871 }, -{ "braille_dots_2567", 0x1002872 }, -{ "braille_dots_12567", 0x1002873 }, -{ "braille_dots_3567", 0x1002874 }, -{ "braille_dots_13567", 0x1002875 }, -{ "braille_dots_23567", 0x1002876 }, -{ "braille_dots_123567", 0x1002877 }, -{ "braille_dots_4567", 0x1002878 }, -{ "braille_dots_14567", 0x1002879 }, -{ "braille_dots_24567", 0x100287A }, -{ "braille_dots_124567", 0x100287B }, -{ "braille_dots_34567", 0x100287C }, -{ "braille_dots_134567", 0x100287D }, -{ "braille_dots_234567", 0x100287E }, -{ "braille_dots_1234567", 0x100287F }, -{ "braille_dots_8", 0x1002880 }, -{ "braille_dots_18", 0x1002881 }, -{ "braille_dots_28", 0x1002882 }, -{ "braille_dots_128", 0x1002883 }, -{ "braille_dots_38", 0x1002884 }, -{ "braille_dots_138", 0x1002885 }, -{ "braille_dots_238", 0x1002886 }, -{ "braille_dots_1238", 0x1002887 }, -{ "braille_dots_48", 0x1002888 }, -{ "braille_dots_148", 0x1002889 }, -{ "braille_dots_248", 0x100288A }, -{ "braille_dots_1248", 0x100288B }, -{ "braille_dots_348", 0x100288C }, -{ "braille_dots_1348", 0x100288D }, -{ "braille_dots_2348", 0x100288E }, -{ "braille_dots_12348", 0x100288F }, -{ "braille_dots_58", 0x1002890 }, -{ "braille_dots_158", 0x1002891 }, -{ "braille_dots_258", 0x1002892 }, -{ "braille_dots_1258", 0x1002893 }, -{ "braille_dots_358", 0x1002894 }, -{ "braille_dots_1358", 0x1002895 }, -{ "braille_dots_2358", 0x1002896 }, -{ "braille_dots_12358", 0x1002897 }, -{ "braille_dots_458", 0x1002898 }, -{ "braille_dots_1458", 0x1002899 }, -{ "braille_dots_2458", 0x100289A }, -{ "braille_dots_12458", 0x100289B }, -{ "braille_dots_3458", 0x100289C }, -{ "braille_dots_13458", 0x100289D }, -{ "braille_dots_23458", 0x100289E }, -{ "braille_dots_123458", 0x100289F }, -{ "braille_dots_68", 0x10028A0 }, -{ "braille_dots_168", 0x10028A1 }, -{ "braille_dots_268", 0x10028A2 }, -{ "braille_dots_1268", 0x10028A3 }, -{ "braille_dots_368", 0x10028A4 }, -{ "braille_dots_1368", 0x10028A5 }, -{ "braille_dots_2368", 0x10028A6 }, -{ "braille_dots_12368", 0x10028A7 }, -{ "braille_dots_468", 0x10028A8 }, -{ "braille_dots_1468", 0x10028A9 }, -{ "braille_dots_2468", 0x10028AA }, -{ "braille_dots_12468", 0x10028AB }, -{ "braille_dots_3468", 0x10028AC }, -{ "braille_dots_13468", 0x10028AD }, -{ "braille_dots_23468", 0x10028AE }, -{ "braille_dots_123468", 0x10028AF }, -{ "braille_dots_568", 0x10028B0 }, -{ "braille_dots_1568", 0x10028B1 }, -{ "braille_dots_2568", 0x10028B2 }, -{ "braille_dots_12568", 0x10028B3 }, -{ "braille_dots_3568", 0x10028B4 }, -{ "braille_dots_13568", 0x10028B5 }, -{ "braille_dots_23568", 0x10028B6 }, -{ "braille_dots_123568", 0x10028B7 }, -{ "braille_dots_4568", 0x10028B8 }, -{ "braille_dots_14568", 0x10028B9 }, -{ "braille_dots_24568", 0x10028BA }, -{ "braille_dots_124568", 0x10028BB }, -{ "braille_dots_34568", 0x10028BC }, -{ "braille_dots_134568", 0x10028BD }, -{ "braille_dots_234568", 0x10028BE }, -{ "braille_dots_1234568", 0x10028BF }, -{ "braille_dots_78", 0x10028C0 }, -{ "braille_dots_178", 0x10028C1 }, -{ "braille_dots_278", 0x10028C2 }, -{ "braille_dots_1278", 0x10028C3 }, -{ "braille_dots_378", 0x10028C4 }, -{ "braille_dots_1378", 0x10028C5 }, -{ "braille_dots_2378", 0x10028C6 }, -{ "braille_dots_12378", 0x10028C7 }, -{ "braille_dots_478", 0x10028C8 }, -{ "braille_dots_1478", 0x10028C9 }, -{ "braille_dots_2478", 0x10028CA }, -{ "braille_dots_12478", 0x10028CB }, -{ "braille_dots_3478", 0x10028CC }, -{ "braille_dots_13478", 0x10028CD }, -{ "braille_dots_23478", 0x10028CE }, -{ "braille_dots_123478", 0x10028CF }, -{ "braille_dots_578", 0x10028D0 }, -{ "braille_dots_1578", 0x10028D1 }, -{ "braille_dots_2578", 0x10028D2 }, -{ "braille_dots_12578", 0x10028D3 }, -{ "braille_dots_3578", 0x10028D4 }, -{ "braille_dots_13578", 0x10028D5 }, -{ "braille_dots_23578", 0x10028D6 }, -{ "braille_dots_123578", 0x10028D7 }, -{ "braille_dots_4578", 0x10028D8 }, -{ "braille_dots_14578", 0x10028D9 }, -{ "braille_dots_24578", 0x10028DA }, -{ "braille_dots_124578", 0x10028DB }, -{ "braille_dots_34578", 0x10028DC }, -{ "braille_dots_134578", 0x10028DD }, -{ "braille_dots_234578", 0x10028DE }, -{ "braille_dots_1234578", 0x10028DF }, -{ "braille_dots_678", 0x10028E0 }, -{ "braille_dots_1678", 0x10028E1 }, -{ "braille_dots_2678", 0x10028E2 }, -{ "braille_dots_12678", 0x10028E3 }, -{ "braille_dots_3678", 0x10028E4 }, -{ "braille_dots_13678", 0x10028E5 }, -{ "braille_dots_23678", 0x10028E6 }, -{ "braille_dots_123678", 0x10028E7 }, -{ "braille_dots_4678", 0x10028E8 }, -{ "braille_dots_14678", 0x10028E9 }, -{ "braille_dots_24678", 0x10028EA }, -{ "braille_dots_124678", 0x10028EB }, -{ "braille_dots_34678", 0x10028EC }, -{ "braille_dots_134678", 0x10028ED }, -{ "braille_dots_234678", 0x10028EE }, -{ "braille_dots_1234678", 0x10028EF }, -{ "braille_dots_5678", 0x10028F0 }, -{ "braille_dots_15678", 0x10028F1 }, -{ "braille_dots_25678", 0x10028F2 }, -{ "braille_dots_125678", 0x10028F3 }, -{ "braille_dots_35678", 0x10028F4 }, -{ "braille_dots_135678", 0x10028F5 }, -{ "braille_dots_235678", 0x10028F6 }, -{ "braille_dots_1235678", 0x10028F7 }, -{ "braille_dots_45678", 0x10028F8 }, -{ "braille_dots_145678", 0x10028F9 }, -{ "braille_dots_245678", 0x10028FA }, -{ "braille_dots_1245678", 0x10028FB }, -{ "braille_dots_345678", 0x10028FC }, -{ "braille_dots_1345678", 0x10028FD }, -{ "braille_dots_2345678", 0x10028FE }, -{ "braille_dots_12345678", 0x10028FF }, -{ "Sinh_ng", 0x1000D82 }, -{ "Sinh_h2", 0x1000D83 }, -{ "Sinh_a", 0x1000D85 }, -{ "Sinh_aa", 0x1000D86 }, -{ "Sinh_ae", 0x1000D87 }, -{ "Sinh_aee", 0x1000D88 }, -{ "Sinh_i", 0x1000D89 }, -{ "Sinh_ii", 0x1000D8A }, -{ "Sinh_u", 0x1000D8B }, -{ "Sinh_uu", 0x1000D8C }, -{ "Sinh_ri", 0x1000D8D }, -{ "Sinh_rii", 0x1000D8E }, -{ "Sinh_lu", 0x1000D8F }, -{ "Sinh_luu", 0x1000D90 }, -{ "Sinh_e", 0x1000D91 }, -{ "Sinh_ee", 0x1000D92 }, -{ "Sinh_ai", 0x1000D93 }, -{ "Sinh_o", 0x1000D94 }, -{ "Sinh_oo", 0x1000D95 }, -{ "Sinh_au", 0x1000D96 }, -{ "Sinh_ka", 0x1000D9A }, -{ "Sinh_kha", 0x1000D9B }, -{ "Sinh_ga", 0x1000D9C }, -{ "Sinh_gha", 0x1000D9D }, -{ "Sinh_ng2", 0x1000D9E }, -{ "Sinh_nga", 0x1000D9F }, -{ "Sinh_ca", 0x1000DA0 }, -{ "Sinh_cha", 0x1000DA1 }, -{ "Sinh_ja", 0x1000DA2 }, -{ "Sinh_jha", 0x1000DA3 }, -{ "Sinh_nya", 0x1000DA4 }, -{ "Sinh_jnya", 0x1000DA5 }, -{ "Sinh_nja", 0x1000DA6 }, -{ "Sinh_tta", 0x1000DA7 }, -{ "Sinh_ttha", 0x1000DA8 }, -{ "Sinh_dda", 0x1000DA9 }, -{ "Sinh_ddha", 0x1000DAA }, -{ "Sinh_nna", 0x1000DAB }, -{ "Sinh_ndda", 0x1000DAC }, -{ "Sinh_tha", 0x1000DAD }, -{ "Sinh_thha", 0x1000DAE }, -{ "Sinh_dha", 0x1000DAF }, -{ "Sinh_dhha", 0x1000DB0 }, -{ "Sinh_na", 0x1000DB1 }, -{ "Sinh_ndha", 0x1000DB3 }, -{ "Sinh_pa", 0x1000DB4 }, -{ "Sinh_pha", 0x1000DB5 }, -{ "Sinh_ba", 0x1000DB6 }, -{ "Sinh_bha", 0x1000DB7 }, -{ "Sinh_ma", 0x1000DB8 }, -{ "Sinh_mba", 0x1000DB9 }, -{ "Sinh_ya", 0x1000DBA }, -{ "Sinh_ra", 0x1000DBB }, -{ "Sinh_la", 0x1000DBD }, -{ "Sinh_va", 0x1000DC0 }, -{ "Sinh_sha", 0x1000DC1 }, -{ "Sinh_ssha", 0x1000DC2 }, -{ "Sinh_sa", 0x1000DC3 }, -{ "Sinh_ha", 0x1000DC4 }, -{ "Sinh_lla", 0x1000DC5 }, -{ "Sinh_fa", 0x1000DC6 }, -{ "Sinh_al", 0x1000DCA }, -{ "Sinh_aa2", 0x1000DCF }, -{ "Sinh_ae2", 0x1000DD0 }, -{ "Sinh_aee2", 0x1000DD1 }, -{ "Sinh_i2", 0x1000DD2 }, -{ "Sinh_ii2", 0x1000DD3 }, -{ "Sinh_u2", 0x1000DD4 }, -{ "Sinh_uu2", 0x1000DD6 }, -{ "Sinh_ru2", 0x1000DD8 }, -{ "Sinh_e2", 0x1000DD9 }, -{ "Sinh_ee2", 0x1000DDA }, -{ "Sinh_ai2", 0x1000DDB }, -{ "Sinh_o2", 0x1000DDC }, -{ "Sinh_oo2", 0x1000DDD }, -{ "Sinh_au2", 0x1000DDE }, -{ "Sinh_lu2", 0x1000DDF }, -{ "Sinh_ruu2", 0x1000DF2 }, -{ "Sinh_luu2", 0x1000DF3 }, -{ "Sinh_kunddaliya", 0x1000DF4 }, { "XF86ModeLock", 0x1008FF01 }, { "XF86MonBrightnessUp", 0x1008FF02 }, { "XF86MonBrightnessDown", 0x1008FF03 }, { "XF86KbdLightOnOff", 0x1008FF04 }, { "XF86KbdBrightnessUp", 0x1008FF05 }, Index: generic/nanosvg.h ================================================================== --- generic/nanosvg.h +++ generic/nanosvg.h @@ -31,26 +31,27 @@ #ifdef __cplusplus extern "C" { #endif -// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. -// -// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. -// -// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! -// -// The shapes in the SVG images are transformed by the viewBox and converted to specified units. -// That is, you should get the same looking data as your designed in your favorite app. -// -// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose -// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. -// -// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. -// DPI (dots-per-inch) controls how the unit conversion is done. -// -// If you don't know or care about the units stuff, "px" and 96 should get you going. +/* NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. + * + * The library suits well for anything from rendering scalable icons in your editor application to prototyping a game. + * + * NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request! + * + * The shapes in the SVG images are transformed by the viewBox and converted to specified units. + * That is, you should get the same looking data as your designed in your favorite app. + * + * NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose + * to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. + * + * The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. + * DPI (dots-per-inch) controls how the unit conversion is done. + * + * If you don't know or care about the units stuff, "px" and 96 should get you going. + */ /* Example Usage: // Load SVG NSVGimage* image; @@ -83,11 +84,11 @@ #ifndef NANOSVG_free #define NANOSVG_free free #endif -// float emulation for MS VC6++ compiler +/* float emulation for MS VC6++ compiler */ #if defined(_MSC_VER) && (_MSC_VER == 1200) #define tanf(a) (float)tan(a) #define cosf(a) (float)cos(a) #define sinf(a) (float)sin(a) #define sqrtf(a) (float)sqrt(a) @@ -96,11 +97,11 @@ #define atan2f(a,b) (float)atan2(a,b) #define ceilf(a) (float)ceil(a) #define fmodf(a,b) (float)fmod(a,b) #define floorf(a) (float)floor(a) #endif -// float emulation for MS VC8++ compiler +/* float emulation for MS VC8++ compiler */ #if defined(_MSC_VER) && (_MSC_VER == 1400) #define fabsf(a) (float)fabs(a) #endif enum NSVGpaintType { @@ -158,68 +159,68 @@ }; } NSVGpaint; typedef struct NSVGpath { - float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... - int npts; // Total number of bezier points. - char closed; // Flag indicating if shapes should be treated as closed. - float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. - struct NSVGpath* next; // Pointer to next path, or NULL if last element. + float* pts; /* Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ... */ + int npts; /* Total number of bezier points. */ + char closed; /* Flag indicating if shapes should be treated as closed. */ + float bounds[4]; /* Tight bounding box of the shape [minx,miny,maxx,maxy]. */ + struct NSVGpath* next; /* Pointer to next path, or NULL if last element. */ } NSVGpath; typedef struct NSVGshape { - char id[64]; // Optional 'id' attr of the shape or its group - NSVGpaint fill; // Fill paint - NSVGpaint stroke; // Stroke paint - float opacity; // Opacity of the shape. - float strokeWidth; // Stroke width (scaled). - float strokeDashOffset; // Stroke dash offset (scaled). - float strokeDashArray[8]; // Stroke dash array (scaled). - char strokeDashCount; // Number of dash values in dash array. - char strokeLineJoin; // Stroke join type. - char strokeLineCap; // Stroke cap type. - float miterLimit; // Miter limit - char fillRule; // Fill rule, see NSVGfillRule. - unsigned char flags; // Logical or of NSVG_FLAGS_* flags - float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. - NSVGpath* paths; // Linked list of paths in the image. - struct NSVGshape* next; // Pointer to next shape, or NULL if last element. + char id[64]; /* Optional 'id' attr of the shape or its group */ + NSVGpaint fill; /* Fill paint */ + NSVGpaint stroke; /* Stroke paint */ + float opacity; /* Opacity of the shape. */ + float strokeWidth; /* Stroke width (scaled). */ + float strokeDashOffset; /* Stroke dash offset (scaled). */ + float strokeDashArray[8]; /* Stroke dash array (scaled). */ + char strokeDashCount; /* Number of dash values in dash array. */ + char strokeLineJoin; /* Stroke join type. */ + char strokeLineCap; /* Stroke cap type. */ + float miterLimit; /* Miter limit */ + char fillRule; /* Fill rule, see NSVGfillRule. */ + unsigned char flags; /* Logical or of NSVG_FLAGS_* flags */ + float bounds[4]; /* Tight bounding box of the shape [minx,miny,maxx,maxy]. */ + NSVGpath* paths; /* Linked list of paths in the image. */ + struct NSVGshape* next; /* Pointer to next shape, or NULL if last element. */ } NSVGshape; typedef struct NSVGimage { - float width; // Width of the image. - float height; // Height of the image. - NSVGshape* shapes; // Linked list of shapes in the image. + float width; /* Width of the image. */ + float height; /* Height of the image. */ + NSVGshape* shapes; /* Linked list of shapes in the image. */ } NSVGimage; -// Parses SVG file from a file, returns SVG image as paths. +/* Parses SVG file from a file, returns SVG image as paths. */ NANOSVG_SCOPE NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi); -// Parses SVG file from a null terminated string, returns SVG image as paths. -// Important note: changes the string. +/* Parses SVG file from a null terminated string, returns SVG image as paths. */ +/* Important note: changes the string. */ NANOSVG_SCOPE NSVGimage* nsvgParse(char* input, const char* units, float dpi); -// Deletes list of paths. +/* Deletes list of paths. */ NANOSVG_SCOPE void nsvgDelete(NSVGimage* image); #ifdef __cplusplus } #endif -#endif // NANOSVG_H +#endif /* NANOSVG_H */ #ifdef NANOSVG_IMPLEMENTATION #include #include #include #define NSVG_PI (3.14159265358979323846264338327f) -#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. +#define NSVG_KAPPA90 (0.5522847493f) /* Length proportional to radius of a cubic bezier handle for 90deg arcs. */ #define NSVG_ALIGN_MIN 0 #define NSVG_ALIGN_MID 1 #define NSVG_ALIGN_MAX 2 #define NSVG_ALIGN_NONE 0 @@ -228,18 +229,18 @@ #define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) #define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) #ifdef _MSC_VER - #pragma warning (disable: 4996) // Switch off security warnings - #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings + #pragma warning (disable: 4996) /* Switch off security warnings */ + #pragma warning (disable: 4100) /* Switch off unreferenced formal parameter warnings */ #ifdef __cplusplus #define NSVG_INLINE inline #else #define NSVG_INLINE #endif - #if !defined(strtoll) // old MSVC versions do not have strtoll() + #if !defined(strtoll) /* old MSVC versions do not have strtoll() */ #define strtoll _strtoi64 #endif #else #define NSVG_INLINE inline #endif @@ -257,21 +258,21 @@ static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } -// Simple XML parser +/* Simple XML parser */ #define NSVG_XML_TAG 1 #define NSVG_XML_CONTENT 2 #define NSVG_XML_MAX_ATTRIBS 256 static void nsvg__parseContent(char* s, void (*contentCb)(void* ud, const char* s), void* ud) { - // Trim start white spaces + /* Trim start white spaces */ while (*s && nsvg__isspace(*s)) s++; if (!*s) return; if (contentCb) (*contentCb)(ud, s); @@ -287,68 +288,68 @@ char* cbname; int start = 0; int end = 0; char quote; - // Skip white space after the '<' + /* Skip white space after the '<' */ while (*s && nsvg__isspace(*s)) s++; - // Check if the tag is end tag + /* Check if the tag is end tag */ if (*s == '/') { s++; end = 1; } else { start = 1; } - // Skip comments, data and preprocessor stuff. + /* Skip comments, data and preprocessor stuff. */ if (!*s || *s == '?' || *s == '!') return; - // Get tag name + /* Get tag name */ cbname = s; while (*s && !nsvg__isspace(*s)) s++; if (*s) { *s++ = '\0'; } - // Get attribs + /* Get attribs */ while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) { char* name = NULL; char* value = NULL; - // Skip white space before the attrib name + /* Skip white space before the attrib name */ while (*s && nsvg__isspace(*s)) s++; if (!*s) break; if (*s == '/') { end = 1; break; } name = s; - // Find end of the attrib name. + /* Find end of the attrib name. */ while (*s && !nsvg__isspace(*s) && *s != '=') s++; if (*s) { *s++ = '\0'; } - // Skip until the beginning of the value. + /* Skip until the beginning of the value. */ while (*s && *s != '\"' && *s != '\'') s++; if (!*s) break; quote = *s; s++; - // Store value and find the end of it. + /* Store value and find the end of it. */ value = s; while (*s && *s != quote) s++; if (*s) { *s++ = '\0'; } - // Store only well formed attributes + /* Store only well formed attributes */ if (name && value) { attr[nattr++] = name; attr[nattr++] = value; } } - // List terminator + /* List terminator */ attr[nattr++] = 0; attr[nattr++] = 0; - // Call callbacks. + /* Call callbacks. */ if (start && startelCb) (*startelCb)(ud, cbname, attr); if (end && endelCb) (*endelCb)(ud, cbname); } @@ -363,17 +364,17 @@ char* s = input; char* mark = s; int state = NSVG_XML_CONTENT; while (*s) { if (*s == '<' && state == NSVG_XML_CONTENT) { - // Start of a tag + /* Start of a tag */ *s++ = '\0'; nsvg__parseContent(mark, contentCb, ud); mark = s; state = NSVG_XML_TAG; } else if (*s == '>' && state == NSVG_XML_TAG) { - // Start of a content or new tag. + /* Start of a content or new tag. */ *s++ = '\0'; nsvg__parseContent(mark, contentCb, ud); nsvg__parseElement(mark, startelCb, endelCb, ud); mark = s; state = NSVG_XML_CONTENT; @@ -613,22 +614,22 @@ float* v0 = &curve[0]; float* v1 = &curve[2]; float* v2 = &curve[4]; float* v3 = &curve[6]; - // Start the bounding box by end points + /* Start the bounding box by end points */ bounds[0] = nsvg__minf(v0[0], v3[0]); bounds[1] = nsvg__minf(v0[1], v3[1]); bounds[2] = nsvg__maxf(v0[0], v3[0]); bounds[3] = nsvg__maxf(v0[1], v3[1]); - // Bezier curve fits inside the convex hull of it's control points. - // If control points are inside the bounds, we're done. + /* Bezier curve fits inside the convex hull of it's control points. */ + /* If control points are inside the bounds, we're done. */ if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds)) return; - // Add bezier curve inflection points in X and Y. + /* Add bezier curve inflection points in X and Y. */ for (i = 0; i < 2; i++) { a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i]; b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i]; c = 3.0 * v1[i] - 3.0 * v0[i]; count = 0; @@ -666,11 +667,11 @@ p->image = (NSVGimage*)NANOSVG_malloc(sizeof(NSVGimage)); if (p->image == NULL) goto error; memset(p->image, 0, sizeof(NSVGimage)); - // Init style + /* Init style */ nsvg__xformIdentity(p->attr[0].xform); memset(p->attr[0].id, 0, sizeof p->attr[0].id); p->attr[0].fillColor = NSVG_RGB(0,0,0); p->attr[0].strokeColor = NSVG_RGB(0,0,0); p->attr[0].opacity = 1; @@ -852,11 +853,11 @@ case NSVG_UNITS_PC: return c.value / 6.0f * p->dpi; case NSVG_UNITS_MM: return c.value / 25.4f * p->dpi; case NSVG_UNITS_CM: return c.value / 2.54f * p->dpi; case NSVG_UNITS_IN: return c.value * p->dpi; case NSVG_UNITS_EM: return c.value * attr->fontSize; - case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; // x-height of Helvetica. + case NSVG_UNITS_EX: return c.value * attr->fontSize * 0.52f; /* x-height of Helvetica. */ case NSVG_UNITS_PERCENT: return orig + c.value / 100.0f * length; default: return c.value; } return c.value; } @@ -886,11 +887,11 @@ int refIter; data = nsvg__findGradientData(p, id); if (data == NULL) return NULL; - // TODO: use ref to fill in all unset values too. + /* TODO: use ref to fill in all unset values too. */ ref = data; refIter = 0; while (ref != NULL) { NSVGgradientData* nextRef = NULL; if (stops == NULL && ref->stops != NULL) { @@ -897,21 +898,21 @@ stops = ref->stops; nstops = ref->nstops; break; } nextRef = nsvg__findGradientData(p, ref->ref); - if (nextRef == ref) break; // prevent infite loops on malformed data + if (nextRef == ref) break; /* prevent infite loops on malformed data */ ref = nextRef; refIter++; - if (refIter > 32) break; // prevent infite loops on malformed data + if (refIter > 32) break; /* prevent infite loops on malformed data */ } if (stops == NULL) return NULL; grad = (NSVGgradient*)NANOSVG_malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1)); if (grad == NULL) return NULL; - // The shape width and height. + /* The shape width and height. */ if (data->units == NSVG_OBJECT_SPACE) { ox = localBounds[0]; oy = localBounds[1]; sw = localBounds[2] - localBounds[0]; sh = localBounds[3] - localBounds[1]; @@ -927,11 +928,11 @@ float x1, y1, x2, y2, dx, dy; x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw); y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh); x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw); y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh); - // Calculate transform aligned to the line + /* Calculate transform aligned to the line */ dx = x2 - x1; dy = y2 - y1; grad->xform[0] = dy; grad->xform[1] = -dx; grad->xform[2] = dx; grad->xform[3] = dy; grad->xform[4] = x1; grad->xform[5] = y1; @@ -940,11 +941,11 @@ cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw); cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh); fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw); fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh); r = nsvg__convertToPixels(p, data->radial.r, 0, sl); - // Calculate transform aligned to the circle + /* Calculate transform aligned to the circle */ grad->xform[0] = r; grad->xform[1] = 0; grad->xform[2] = 0; grad->xform[3] = r; grad->xform[4] = cx; grad->xform[5] = cy; grad->fx = fx / r; grad->fy = fy / r; @@ -1028,11 +1029,11 @@ shape->opacity = attr->opacity; shape->paths = p->plist; p->plist = NULL; - // Calculate shape bounds + /* Calculate shape bounds */ shape->bounds[0] = shape->paths->bounds[0]; shape->bounds[1] = shape->paths->bounds[1]; shape->bounds[2] = shape->paths->bounds[2]; shape->bounds[3] = shape->paths->bounds[3]; for (path = shape->paths->next; path != NULL; path = path->next) { @@ -1040,11 +1041,11 @@ shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]); shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]); shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]); } - // Set fill + /* Set fill */ if (attr->hasFill == 0) { shape->fill.type = NSVG_PAINT_NONE; } else if (attr->hasFill == 1) { shape->fill.type = NSVG_PAINT_COLOR; shape->fill.color = attr->fillColor; @@ -1057,11 +1058,11 @@ if (shape->fill.gradient == NULL) { shape->fill.type = NSVG_PAINT_NONE; } } - // Set stroke + /* Set stroke */ if (attr->hasStroke == 0) { shape->stroke.type = NSVG_PAINT_NONE; } else if (attr->hasStroke == 1) { shape->stroke.type = NSVG_PAINT_COLOR; shape->stroke.color = attr->strokeColor; @@ -1073,14 +1074,14 @@ shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type); if (shape->stroke.gradient == NULL) shape->stroke.type = NSVG_PAINT_NONE; } - // Set flags + /* Set flags */ shape->flags = ((attr->visible & NSVG_VIS_DISPLAY) && (attr->visible & NSVG_VIS_VISIBLE) ? NSVG_FLAGS_VISIBLE : 0x00); - // Add to tail + /* Add to tail */ if (p->image->shapes == NULL) p->image->shapes = shape; else p->shapesTail->next = shape; p->shapesTail = shape; @@ -1103,11 +1104,11 @@ return; if (closed) nsvg__lineTo(p, p->pts[0], p->pts[1]); - // Expect 1 + N*3 points (N = number of cubic bezier segments). + /* Expect 1 + N*3 points (N = number of cubic bezier segments). */ if ((p->npts % 3) != 1) return; path = (NSVGpath*)NANOSVG_malloc(sizeof(NSVGpath)); if (path == NULL) goto error; @@ -1116,15 +1117,15 @@ path->pts = (float*)NANOSVG_malloc(p->npts*2*sizeof(float)); if (path->pts == NULL) goto error; path->closed = closed; path->npts = p->npts; - // Transform path. + /* Transform path. */ for (i = 0; i < p->npts; ++i) nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform); - // Find bounds + /* Find bounds */ for (i = 0; i < path->npts-1; i += 3) { curve = &path->pts[i*2]; nsvg__curveBounds(bounds, curve); if (i == 0) { path->bounds[0] = bounds[0]; @@ -1149,11 +1150,11 @@ if (path->pts != NULL) NANOSVG_free(path->pts); NANOSVG_free(path); } } -// We roll our own string to float because the std library one uses locale and messes things up. +/* We roll our own string to float because the std library one uses locale and messes things up. */ static double nsvg__atof(const char* s) { char* cur = (char*)s; char* end = NULL; double res = 0.0, sign = 1.0; @@ -1162,21 +1163,21 @@ #else long long intPart = 0, fracPart = 0; #endif char hasIntPart = 0, hasFracPart = 0; - // Parse optional sign + /* Parse optional sign */ if (*cur == '+') { cur++; } else if (*cur == '-') { sign = -1; cur++; } - // Parse integer part + /* Parse integer part */ if (nsvg__isdigit(*cur)) { - // Parse digit sequence + /* Parse digit sequence */ #if defined(_MSC_VER) && (_MSC_VER == 1200) intPart = strtol(cur, &end, 10); #else intPart = strtoll(cur, &end, 10); #endif @@ -1185,15 +1186,15 @@ hasIntPart = 1; cur = end; } } - // Parse fractional part. + /* Parse fractional part. */ if (*cur == '.') { - cur++; // Skip '.' + cur++; /* Skip '.' */ if (nsvg__isdigit(*cur)) { - // Parse digit sequence + /* Parse digit sequence */ #if defined(_MSC_VER) && (_MSC_VER == 1200) fracPart = strtol(cur, &end, 10); #else fracPart = strtoll(cur, &end, 10); #endif @@ -1203,19 +1204,19 @@ cur = end; } } } - // A valid number should have integer or fractional part. + /* A valid number should have integer or fractional part. */ if (!hasIntPart && !hasFracPart) return 0.0; - // Parse optional exponent + /* Parse optional exponent */ if (*cur == 'e' || *cur == 'E') { int expPart = 0; - cur++; // skip 'E' - expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + cur++; /* skip 'E' */ + expPart = strtol(cur, &end, 10); /* Parse digit sequence with sign */ if (cur != end) { res *= pow(10.0, (double)expPart); } } @@ -1226,31 +1227,31 @@ static const char* nsvg__parseNumber(const char* s, char* it, const int size) { const int last = size-1; int i = 0; - // sign + /* sign */ if (*s == '-' || *s == '+') { if (i < last) it[i++] = *s; s++; } - // integer part + /* integer part */ while (*s && nsvg__isdigit(*s)) { if (i < last) it[i++] = *s; s++; } if (*s == '.') { - // decimal point + /* decimal point */ if (i < last) it[i++] = *s; s++; - // fraction part + /* fraction part */ while (*s && nsvg__isdigit(*s)) { if (i < last) it[i++] = *s; s++; } } - // exponent + /* exponent */ if (*s == 'e' || *s == 'E') { if (i < last) it[i++] = *s; s++; if (*s == '-' || *s == '+') { if (i < last) it[i++] = *s; @@ -1267,17 +1268,17 @@ } static const char* nsvg__getNextPathItem(const char* s, char* it) { it[0] = '\0'; - // Skip white spaces and commas + /* Skip white spaces and commas */ while (*s && (nsvg__isspace(*s) || *s == ',')) s++; if (!*s) return s; if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) { s = nsvg__parseNumber(s, it, 64); } else { - // Parse command + /* Parse command */ it[0] = *s++; it[1] = '\0'; return s; } @@ -1284,39 +1285,26 @@ return s; } static unsigned int nsvg__parseColorHex(const char* str) { - unsigned int c = 0, r = 0, g = 0, b = 0; - int n = 0; - str++; // skip # - // Calculate number of characters. - while(str[n] && !nsvg__isspace(str[n])) - n++; - if (n == 6) { - sscanf(str, "%x", &c); - } else if (n == 3) { - sscanf(str, "%x", &c); - c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8); - c |= c<<4; - } - r = (c >> 16) & 0xff; - g = (c >> 8) & 0xff; - b = c & 0xff; - return NSVG_RGB(r,g,b); + unsigned int r=0, g=0, b=0; + if (sscanf(str, "#%2x%2x%2x", &r, &g, &b) == 3 ) /* 2 digit hex */ + return NSVG_RGB(r, g, b); + if (sscanf(str, "#%1x%1x%1x", &r, &g, &b) == 3 ) /* 1 digit hex, e.g. #abc -> 0xccbbaa */ + return NSVG_RGB(r*17, g*17, b*17); /* same effect as (r<<4|r), (g<<4|g), .. */ + return NSVG_RGB(128, 128, 128); } static unsigned int nsvg__parseColorRGB(const char* str) { - int r = -1, g = -1, b = -1; - char s1[32]="", s2[32]=""; - sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b); - if (strchr(s1, '%')) { - return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100); - } else { - return NSVG_RGB(r,g,b); - } + unsigned int r=0, g=0, b=0; + if (sscanf(str, "rgb(%u, %u, %u)", &r, &g, &b) == 3) /* decimal integers */ + return NSVG_RGB(r, g, b); + if (sscanf(str, "rgb(%u%%, %u%%, %u%%)", &r, &g, &b) == 3) /* decimal integer percentage */ + return NSVG_RGB(r*255/100, g*255/100, b*255/100); + return NSVG_RGB(128, 128, 128); } typedef struct NSVGNamedColor { const char* name; unsigned int color; @@ -1541,15 +1529,15 @@ return NSVG_UNITS_USER; } static int nsvg__isCoordinate(const char* s) { - // optional sign + /* optional sign */ if (*s == '-' || *s == '+') s++; - // must have at least one digit - return nsvg__isdigit(*s); + /* must have at least one digit, or start by a dot */ + return (nsvg__isdigit(*s) || *s == '.'); } static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) { NSVGcoordinate coord = {0, NSVG_UNITS_USER}; @@ -1721,11 +1709,11 @@ } static void nsvg__parseUrl(char* id, const char* str) { int i = 0; - str += 4; // "url("; + str += 4; /* "url("; */ if (*str == '#') str++; while (i < 63 && *str != ')') { id[i] = *str++; i++; @@ -1739,11 +1727,11 @@ return NSVG_CAP_BUTT; else if (strcmp(str, "round") == 0) return NSVG_CAP_ROUND; else if (strcmp(str, "square") == 0) return NSVG_CAP_SQUARE; - // TODO: handle inherit. + /* TODO: handle inherit. */ return NSVG_CAP_BUTT; } static char nsvg__parseLineJoin(const char* str) { @@ -1751,31 +1739,31 @@ return NSVG_JOIN_MITER; else if (strcmp(str, "round") == 0) return NSVG_JOIN_ROUND; else if (strcmp(str, "bevel") == 0) return NSVG_JOIN_BEVEL; - // TODO: handle inherit. + /* TODO: handle inherit. */ return NSVG_JOIN_MITER; } static char nsvg__parseFillRule(const char* str) { if (strcmp(str, "nonzero") == 0) return NSVG_FILLRULE_NONZERO; else if (strcmp(str, "evenodd") == 0) return NSVG_FILLRULE_EVENODD; - // TODO: handle inherit. + /* TODO: handle inherit. */ return NSVG_FILLRULE_NONZERO; } static const char* nsvg__getNextDashItem(const char* s, char* it) { int n = 0; it[0] = '\0'; - // Skip white spaces and commas + /* Skip white spaces and commas */ while (*s && (nsvg__isspace(*s) || *s == ',')) s++; - // Advance until whitespace, comma or end. + /* Advance until whitespace, comma or end. */ while (*s && (!nsvg__isspace(*s) && *s != ',')) { if (n < 63) it[n++] = *s; s++; } @@ -1787,15 +1775,15 @@ { char item[64]; int count = 0, i; float sum = 0.0f; - // Handle "none" + /* Handle "none" */ if (str[0] == 'n') return 0; - // Parse dashes + /* Parse dashes */ while (*str) { str = nsvg__getNextDashItem(str, item); if (!*item) break; if (count < NSVG_MAX_DASHES) strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p))); @@ -1820,11 +1808,11 @@ if (strcmp(name, "style") == 0) { nsvg__parseStyle(p, value); } else if (strcmp(name, "display") == 0) { if (strcmp(value, "none") == 0) attr->visible &= ~NSVG_VIS_DISPLAY; - // Don't reset ->visible on display:inline, one display:none hides the whole subtree + /* Don't reset ->visible on display:inline, one display:none hides the whole subtree */ } else if (strcmp(name, "visibility") == 0) { if (strcmp(value, "hidden") == 0) { attr->visible &= ~NSVG_VIS_VISIBLE; } else if (strcmp(value, "visible") == 0) { @@ -1912,11 +1900,11 @@ str = start; while (str < end && *str != ':') ++str; val = str; - // Right Trim + /* Right Trim */ while (str > start && (*str == ':' || nsvg__isspace(*str))) --str; ++str; n = (int)(str - start); if (n > 511) n = 511; @@ -1937,17 +1925,17 @@ { const char* start; const char* end; while (*str) { - // Left Trim + /* Left Trim */ while(*str && nsvg__isspace(*str)) ++str; start = str; while(*str && *str != ';') ++str; end = str; - // Right Trim + /* Right Trim */ while (end > start && (*end == ';' || nsvg__isspace(*end))) --end; ++end; nsvg__parseNameValue(p, start, end); if (*str) ++str; @@ -2118,11 +2106,11 @@ cy = args[1]; x2 = args[2]; y2 = args[3]; } - // Convert to cubic bezier + /* Convert to cubic bezier */ cx1 = x1 + 2.0f/3.0f*(cx - x1); cy1 = y1 + 2.0f/3.0f*(cy - y1); cx2 = x2 + 2.0f/3.0f*(cx - x2); cy2 = y2 + 2.0f/3.0f*(cy - y2); @@ -2151,11 +2139,11 @@ } cx = 2*x1 - *cpx2; cy = 2*y1 - *cpy2; - // Convert to cubix bezier + /* Convert to cubix bezier */ cx1 = x1 + 2.0f/3.0f*(cx - x1); cy1 = y1 + 2.0f/3.0f*(cy - y1); cx2 = x2 + 2.0f/3.0f*(cx - x2); cy2 = y2 + 2.0f/3.0f*(cy - y2); @@ -2183,11 +2171,11 @@ return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r); } static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) { - // Ported from canvg (https://code.google.com/p/canvg/) + /* Ported from canvg (https://code.google.com/p/canvg/) */ float rx, ry, rotx; float x1, y1, x2, y2, cx, cy, dx, dy, d; float x1p, y1p, cxp, cyp, s, sa, sb; float ux, uy, vx, vy, a1, da; float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6]; @@ -2194,18 +2182,18 @@ float sinrx, cosrx; int fa, fs; int i, ndivs; float hda, kappa; - rx = fabsf(args[0]); // y radius - ry = fabsf(args[1]); // x radius - rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle - fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc - fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction - x1 = *cpx; // start point + rx = fabsf(args[0]); /* y radius */ + ry = fabsf(args[1]); /* x radius */ + rotx = args[2] / 180.0f * NSVG_PI; /* x rotation angle */ + fa = fabsf(args[3]) > 1e-6 ? 1 : 0; /* Large arc */ + fs = fabsf(args[4]) > 1e-6 ? 1 : 0; /* Sweep direction */ + x1 = *cpx; /* start point */ y1 = *cpy; - if (rel) { // end point + if (rel) { /* end point */ x2 = *cpx + args[5]; y2 = *cpy + args[6]; } else { x2 = args[5]; y2 = args[6]; @@ -2213,32 +2201,32 @@ dx = x1 - x2; dy = y1 - y2; d = sqrtf(dx*dx + dy*dy); if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) { - // The arc degenerates to a line + /* The arc degenerates to a line */ nsvg__lineTo(p, x2, y2); *cpx = x2; *cpy = y2; return; } sinrx = sinf(rotx); cosrx = cosf(rotx); - // Convert to center point parameterization. - // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes - // 1) Compute x1', y1' + /* Convert to center point parameterization. */ + /* http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes */ + /* 1) Compute x1', y1' */ x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f; y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f; d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry); if (d > 1) { d = sqrtf(d); rx *= d; ry *= d; } - // 2) Compute cx', cy' + /* 2) Compute cx', cy' */ s = 0.0f; sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p); sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p); if (sa < 0.0f) sa = 0.0f; if (sb > 0.0f) @@ -2246,49 +2234,54 @@ if (fa == fs) s = -s; cxp = s * rx * y1p / ry; cyp = s * -ry * x1p / rx; - // 3) Compute cx,cy from cx',cy' + /* 3) Compute cx,cy from cx',cy' */ cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp; cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp; - // 4) Calculate theta1, and delta theta. + /* 4) Calculate theta1, and delta theta. */ ux = (x1p - cxp) / rx; uy = (y1p - cyp) / ry; vx = (-x1p - cxp) / rx; vy = (-y1p - cyp) / ry; - a1 = nsvg__vecang(1.0f,0.0f, ux,uy); // Initial angle - da = nsvg__vecang(ux,uy, vx,vy); // Delta angle + a1 = nsvg__vecang(1.0f,0.0f, ux,uy); /* Initial angle */ + da = nsvg__vecang(ux,uy, vx,vy); /* Delta angle */ -// if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; -// if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; +/* if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; */ +/* if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; */ if (fs == 0 && da > 0) da -= 2 * NSVG_PI; else if (fs == 1 && da < 0) da += 2 * NSVG_PI; - // Approximate the arc using cubic spline segments. + /* Approximate the arc using cubic spline segments. */ t[0] = cosrx; t[1] = sinrx; t[2] = -sinrx; t[3] = cosrx; t[4] = cx; t[5] = cy; - // Split arc into max 90 degree segments. - // The loop assumes an iteration per end point (including start and end), this +1. + /* Split arc into max 90 degree segments. */ + /* The loop assumes an iteration per end point (including start and end), this +1. */ ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f); hda = (da / (float)ndivs) / 2.0f; - kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda)); + /* Fix for ticket #179: division by 0: avoid cotangens around 0 (infinite) */ + if ((hda < 1e-3f) && (hda > -1e-3f)) + hda *= 0.5f; + else + hda = (1.0f - cosf(hda)) / sinf(hda); + kappa = fabsf(4.0f / 3.0f * hda); if (da < 0.0f) kappa = -kappa; for (i = 0; i <= ndivs; i++) { a = a1 + da * ((float)i/(float)ndivs); dx = cosf(a); dy = sinf(a); - nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position - nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent + nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); /* position */ + nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); /* tangent */ if (i > 0) nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y); px = x; py = y; ptanx = tanx; @@ -2342,12 +2335,12 @@ if (nargs >= rargs) { switch (cmd) { case 'm': case 'M': nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0); - // Moveto can be followed by multiple coordinate pairs, - // which should be treated as linetos. + /* Moveto can be followed by multiple coordinate pairs, */ + /* which should be treated as linetos. */ cmd = (cmd == 'm') ? 'l' : 'L'; rargs = nsvg__getArgsPerElement(cmd); cpx2 = cpx; cpy2 = cpy; initPoint = 1; break; @@ -2398,46 +2391,46 @@ nargs = 0; } } else { cmd = item[0]; if (cmd == 'M' || cmd == 'm') { - // Commit path. + /* Commit path. */ if (p->npts > 0) nsvg__addPath(p, closedFlag); - // Start new subpath. + /* Start new subpath. */ nsvg__resetPath(p); closedFlag = 0; nargs = 0; } else if (initPoint == 0) { - // Do not allow other commands until initial point has been set (moveTo called once). + /* Do not allow other commands until initial point has been set (moveTo called once). */ cmd = '\0'; } if (cmd == 'Z' || cmd == 'z') { closedFlag = 1; - // Commit path. + /* Commit path. */ if (p->npts > 0) { - // Move current point to first point + /* Move current point to first point */ cpx = p->pts[0]; cpy = p->pts[1]; cpx2 = cpx; cpy2 = cpy; nsvg__addPath(p, closedFlag); } - // Start new subpath. + /* Start new subpath. */ nsvg__resetPath(p); nsvg__moveTo(p, cpx, cpy); closedFlag = 0; nargs = 0; } rargs = nsvg__getArgsPerElement(cmd); if (rargs == -1) { - // Command not recognized + /* Command not recognized */ cmd = '\0'; rargs = 0; } } } - // Commit path. + /* Commit path. */ if (p->npts) nsvg__addPath(p, closedFlag); } nsvg__addShape(p); @@ -2447,11 +2440,11 @@ { float x = 0.0f; float y = 0.0f; float w = 0.0f; float h = 0.0f; - float rx = -1.0f; // marks not set + float rx = -1.0f; /* marks not set */ float ry = -1.0f; int i; for (i = 0; attr[i]; i += 2) { if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { @@ -2478,11 +2471,11 @@ nsvg__moveTo(p, x, y); nsvg__lineTo(p, x+w, y); nsvg__lineTo(p, x+w, y+h); nsvg__lineTo(p, x, y+h); } else { - // Rounded rectangle + /* Rounded rectangle */ nsvg__moveTo(p, x+rx, y); nsvg__lineTo(p, x+w-rx, y); nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry); nsvg__lineTo(p, x+w, y+h-ry); nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h); @@ -2635,28 +2628,28 @@ p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); } else if (strcmp(attr[i], "viewBox") == 0) { sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight); } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { if (strstr(attr[i + 1], "none") != 0) { - // No uniform scaling + /* No uniform scaling */ p->alignType = NSVG_ALIGN_NONE; } else { - // Parse X align + /* Parse X align */ if (strstr(attr[i + 1], "xMin") != 0) p->alignX = NSVG_ALIGN_MIN; else if (strstr(attr[i + 1], "xMid") != 0) p->alignX = NSVG_ALIGN_MID; else if (strstr(attr[i + 1], "xMax") != 0) p->alignX = NSVG_ALIGN_MAX; - // Parse X align + /* Parse X align */ if (strstr(attr[i + 1], "yMin") != 0) p->alignY = NSVG_ALIGN_MIN; else if (strstr(attr[i + 1], "yMid") != 0) p->alignY = NSVG_ALIGN_MID; else if (strstr(attr[i + 1], "yMax") != 0) p->alignY = NSVG_ALIGN_MAX; - // Parse meet/slice + /* Parse meet/slice */ p->alignType = NSVG_ALIGN_MEET; if (strstr(attr[i + 1], "slice") != 0) p->alignType = NSVG_ALIGN_SLICE; } } @@ -2747,19 +2740,19 @@ for (i = 0; attr[i]; i += 2) { nsvg__parseAttr(p, attr[i], attr[i + 1]); } - // Add stop to the last gradient. + /* Add stop to the last gradient. */ grad = p->gradients; if (grad == NULL) return; grad->nstops++; grad->stops = (NSVGgradientStop*)NANOSVG_realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops); if (grad->stops == NULL) return; - // Insert + /* Insert */ idx = grad->nstops-1; for (i = 0; i < grad->nstops-1; i++) { if (curAttr->stopOffset < grad->stops[i].offset) { idx = i; break; @@ -2779,11 +2772,11 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr) { NSVGparser* p = (NSVGparser*)ud; if (p->defsFlag) { - // Skip everything but gradients in defs + /* Skip everything but gradients in defs */ if (strcmp(el, "linearGradient") == 0) { nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT); } else if (strcmp(el, "radialGradient") == 0) { nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT); } else if (strcmp(el, "stop") == 0) { @@ -2794,11 +2787,11 @@ if (strcmp(el, "g") == 0) { nsvg__pushAttr(p); nsvg__parseAttribs(p, attr); } else if (strcmp(el, "path") == 0) { - if (p->pathFlag) // Do not allow nested paths. + if (p->pathFlag) /* Do not allow nested paths. */ return; nsvg__pushAttr(p); nsvg__parsePath(p, attr); nsvg__popAttr(p); } else if (strcmp(el, "rect") == 0) { @@ -2947,11 +2940,11 @@ { if (type == NSVG_ALIGN_MIN) return 0; else if (type == NSVG_ALIGN_MAX) return container - content; - // mid + /* mid */ return (container - content) * 0.5f; } static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) { @@ -2969,11 +2962,11 @@ NSVGpath* path; float tx, ty, sx, sy, us, bounds[4], t[6], avgs; int i; float* pt; - // Guess image size if not set completely. + /* Guess image size if not set completely. */ nsvg__imageBounds(p, bounds); if (p->viewWidth == 0) { if (p->image->width > 0) { p->viewWidth = p->image->width; @@ -2997,27 +2990,27 @@ tx = -p->viewMinx; ty = -p->viewMiny; sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0; sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0; - // Unit scaling + /* Unit scaling */ us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f); - // Fix aspect ratio + /* Fix aspect ratio */ if (p->alignType == NSVG_ALIGN_MEET) { - // fit whole image into viewbox + /* fit whole image into viewbox */ sx = sy = nsvg__minf(sx, sy); tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; } else if (p->alignType == NSVG_ALIGN_SLICE) { - // fill whole viewbox with image + /* fill whole viewbox with image */ sx = sy = nsvg__maxf(sx, sy); tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx; ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy; } - // Transform + /* Transform */ sx *= us; sy *= us; avgs = (sx+sy) / 2.0f; for (shape = p->image->shapes; shape != NULL; shape = shape->next) { shape->bounds[0] = (shape->bounds[0] + tx) * sx; @@ -3066,11 +3059,11 @@ } p->dpi = dpi; nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); - // Scale to viewBox + /* Scale to viewBox */ nsvg__scaleToViewbox(p, units); ret = p->image; p->image = NULL; @@ -3093,11 +3086,11 @@ size = ftell(fp); fseek(fp, 0, SEEK_SET); data = (char*)NANOSVG_malloc(size+1); if (data == NULL) goto error; if (fread(data, 1, size, fp) != size) goto error; - data[size] = '\0'; // Must be null terminated. + data[size] = '\0'; /* Must be null terminated. */ fclose(fp); image = nsvgParse(data, units, dpi); NANOSVG_free(data); return image; Index: generic/nanosvgrast.h ================================================================== --- generic/nanosvgrast.h +++ generic/nanosvgrast.h @@ -57,35 +57,36 @@ unsigned char* img = malloc(w*h*4); // Rasterize nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4); */ -// Allocated rasterizer context. +/* Allocated rasterizer context. */ NANOSVG_SCOPE NSVGrasterizer* nsvgCreateRasterizer(void); -// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) -// r - pointer to rasterizer context -// image - pointer to image to rasterize -// tx,ty - image offset (applied after scaling) -// scale - image scale -// dst - pointer to destination image data, 4 bytes per pixel (RGBA) -// w - width of the image to render -// h - height of the image to render -// stride - number of bytes per scaleline in the destination buffer +/* Rasterizes SVG image, returns RGBA image (non-premultiplied alpha) + * r - pointer to rasterizer context + * image - pointer to image to rasterize + * tx,ty - image offset (applied after scaling) + * scale - image scale + * dst - pointer to destination image data, 4 bytes per pixel (RGBA) + * w - width of the image to render + * h - height of the image to render + * stride - number of bytes per scaleline in the destination buffer NANOSVG_SCOPE void nsvgRasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst, int w, int h, int stride); + */ -// Deletes rasterizer context. +/* Deletes rasterizer context. */ NANOSVG_SCOPE void nsvgDeleteRasterizer(NSVGrasterizer*); #ifdef __cplusplus } #endif -#endif // NANOSVGRAST_H +#endif /* NANOSVGRAST_H */ #ifdef NANOSVGRAST_IMPLEMENTATION #include @@ -200,21 +201,21 @@ static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur) { NSVGmemPage *newp; - // If using existing chain, return the next page in chain + /* If using existing chain, return the next page in chain */ if (cur != NULL && cur->next != NULL) { return cur->next; } - // Alloc new page + /* Alloc new page */ newp = (NSVGmemPage*)NANOSVG_malloc(sizeof(NSVGmemPage)); if (newp == NULL) return NULL; memset(newp, 0, sizeof(NSVGmemPage)); - // Add to linked list + /* Add to linked list */ if (cur != NULL) cur->next = newp; else r->pages = newp; @@ -300,11 +301,11 @@ static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1) { NSVGedge* e; - // Skip horizontal edges + /* Skip horizontal edges */ if (y0 == y1) return; if (r->nedges+1 > r->cedges) { r->cedges = r->cedges > 0 ? r->cedges * 2 : 64; @@ -386,19 +387,19 @@ int i, j; NSVGpath* path; for (path = shape->paths; path != NULL; path = path->next) { r->npoints = 0; - // Flatten path + /* Flatten path */ nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); for (i = 0; i < path->npts-1; i += 3) { float* p = &path->pts[i*2]; nsvg__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); } - // Close path + /* Close path */ nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0); - // Build edges + /* Build edges */ for (i = 0, j = r->npoints-1; i < r->npoints; j = i++) nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y); } } @@ -617,24 +618,24 @@ return divs; } static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth) { - int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); // Calculate divisions per half circle. + int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol); /* Calculate divisions per half circle. */ NSVGpoint 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}; NSVGpoint* p0, *p1; int j, s, e; - // Build stroke edges + /* Build stroke edges */ if (closed) { - // Looping + /* Looping */ p0 = &points[npoints-1]; p1 = &points[0]; s = 0; e = npoints; } else { - // Add cap + /* Add cap */ p0 = &points[0]; p1 = &points[1]; s = 1; e = npoints-1; } @@ -642,11 +643,11 @@ if (closed) { nsvg__initClosed(&left, &right, p0, p1, lineWidth); firstLeft = left; firstRight = right; } else { - // Add cap + /* Add cap */ float dx = p1->x - p0->x; float dy = p1->y - p0->y; nsvg__normalize(&dx, &dy); if (lineCap == NSVG_CAP_BUTT) nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0); @@ -669,15 +670,15 @@ } p0 = p1++; } if (closed) { - // Loop it + /* Loop it */ nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y); nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y); } else { - // Add cap + /* Add cap */ float dx = p1->x - p0->x; float dy = p1->y - p0->y; nsvg__normalize(&dx, &dy); if (lineCap == NSVG_CAP_BUTT) nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1); @@ -694,28 +695,28 @@ NSVGpoint* p0, *p1; p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; for (i = 0; i < r->npoints; i++) { - // Calculate segment direction and length + /* Calculate segment direction and length */ p0->dx = p1->x - p0->x; p0->dy = p1->y - p0->y; p0->len = nsvg__normalize(&p0->dx, &p0->dy); - // Advance + /* Advance */ p0 = p1++; } - // calculate joins + /* calculate joins */ p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; for (j = 0; j < r->npoints; j++) { float dlx0, dly0, dlx1, dly1, dmr2, cross; dlx0 = p0->dy; dly0 = -p0->dx; dlx1 = p1->dy; dly1 = -p1->dx; - // Calculate extrusions + /* Calculate extrusions */ p1->dmx = (dlx0 + dlx1) * 0.5f; p1->dmy = (dly0 + dly1) * 0.5f; dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy; if (dmr2 > 0.000001f) { float s2 = 1.0f / dmr2; @@ -724,19 +725,19 @@ } p1->dmx *= s2; p1->dmy *= s2; } - // Clear flags, but keep the corner. + /* Clear flags, but keep the corner. */ p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0; - // Keep track of left turns. + /* Keep track of left turns. */ cross = p1->dx * p0->dy - p0->dx * p1->dy; if (cross > 0.0f) p1->flags |= NSVG_PT_LEFT; - // Check to see if the corner needs to be beveled. + /* Check to see if the corner needs to be beveled. */ if (p1->flags & NSVG_PT_CORNER) { if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) { p1->flags |= NSVG_PT_BEVEL; } } @@ -754,11 +755,11 @@ int lineJoin = shape->strokeLineJoin; int lineCap = shape->strokeLineCap; float lineWidth = shape->strokeWidth * scale; for (path = shape->paths; path != NULL; path = path->next) { - // Flatten path + /* Flatten path */ r->npoints = 0; nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER); for (i = 0; i < path->npts-1; i += 3) { float* p = &path->pts[i*2]; nsvg__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); @@ -766,11 +767,11 @@ if (r->npoints < 2) continue; closed = path->closed; - // If the first and last points are the same, remove the last, mark as closed path. + /* If the first and last points are the same, remove the last, mark as closed path. */ p0 = &r->points[r->npoints-1]; p1 = &r->points[0]; if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) { r->npoints--; p0 = &r->points[r->npoints-1]; @@ -783,24 +784,24 @@ NSVGpoint cur; if (closed) nsvg__appendPathPoint(r, r->points[0]); - // Duplicate points -> points2. + /* Duplicate points -> points2. */ nsvg__duplicatePoints(r); r->npoints = 0; cur = r->points2[0]; nsvg__appendPathPoint(r, cur); - // Figure out dash offset. + /* Figure out dash offset. */ allDashLen = 0; for (j = 0; j < shape->strokeDashCount; j++) allDashLen += shape->strokeDashArray[j]; if (shape->strokeDashCount & 1) allDashLen *= 2.0f; - // Find location inside pattern + /* Find location inside pattern */ dashOffset = fmodf(shape->strokeDashOffset, allDashLen); if (dashOffset < 0.0f) dashOffset += allDashLen; while (dashOffset > shape->strokeDashArray[idash]) { @@ -813,26 +814,26 @@ float dx = r->points2[j].x - cur.x; float dy = r->points2[j].y - cur.y; float dist = sqrtf(dx*dx + dy*dy); if ((totalDist + dist) > dashLen) { - // Calculate intermediate point + /* Calculate intermediate point */ float d = (dashLen - totalDist) / dist; float x = cur.x + dx * d; float y = cur.y + dy * d; nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER); - // Stroke + /* Stroke */ if (r->npoints > 1 && dashState) { nsvg__prepareStroke(r, miterLimit, lineJoin); nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); } - // Advance dash pattern + /* Advance dash pattern */ dashState = !dashState; idash = (idash+1) % shape->strokeDashCount; dashLen = shape->strokeDashArray[idash] * scale; - // Restart + /* Restart */ cur.x = x; cur.y = y; cur.flags = NSVG_PT_CORNER; totalDist = 0.0f; r->npoints = 0; @@ -842,11 +843,11 @@ cur = r->points2[j]; nsvg__appendPathPoint(r, cur); j++; } } - // Stroke any leftover path + /* Stroke any leftover path */ if (r->npoints > 1 && dashState) nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth); } else { nsvg__prepareStroke(r, miterLimit, lineJoin); nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth); @@ -869,28 +870,28 @@ { NSVGactiveEdge* z; float dxdy; if (r->freelist != NULL) { - // Restore from freelist. + /* Restore from freelist. */ z = r->freelist; r->freelist = z->next; } else { - // Alloc new edge. + /* Alloc new edge. */ z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge)); if (z == NULL) return NULL; } dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); -// STBTT_assert(e->y0 <= start_point); - // round dx down to avoid going too far +/* STBTT_assert(e->y0 <= start_point); */ + /* round dx down to avoid going too far */ if (dxdy < 0) z->dx = (int)(-floorf(NSVG__FIX * -dxdy)); else z->dx = (int)floorf(NSVG__FIX * dxdy); z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); -// z->x -= off_x * FIX; +/* z->x -= off_x * FIX; */ z->ey = e->y1; z->next = 0; z->dir = e->dir; return z; @@ -908,56 +909,57 @@ int j = x1 >> NSVG__FIXSHIFT; if (i < *xmin) *xmin = i; if (j > *xmax) *xmax = j; if (i < len && j >= 0) { if (i == j) { - // x0,x1 are the same pixel, so compute combined coverage + /* x0,x1 are the same pixel, so compute combined coverage */ scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); } else { - if (i >= 0) // add antialiasing for x0 + if (i >= 0) /* add antialiasing for x0 */ scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); else - i = -1; // clip + i = -1; /* clip */ - if (j < len) // add antialiasing for x1 + if (j < len) /* add antialiasing for x1 */ scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); else - j = len; // clip + j = len; /* clip */ - for (++i; i < j; ++i) // fill pixels between x0 and x1 + for (++i; i < j; ++i) /* fill pixels between x0 and x1 */ scanline[i] = (unsigned char)(scanline[i] + maxWeight); } } } -// note: this routine clips fills that extend off the edges... ideally this -// wouldn't happen, but it could happen if the truetype glyph bounding boxes -// are wrong, or if the user supplies a too-small bitmap +/* note: this routine clips fills that extend off the edges... ideally this + * wouldn't happen, but it could happen if the truetype glyph bounding boxes + * are wrong, or if the user supplies a too-small bitmap + */ static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule) { - // non-zero winding fill + /* non-zero winding fill */ int x0 = 0, w = 0; if (fillRule == NSVG_FILLRULE_NONZERO) { - // Non-zero + /* Non-zero */ while (e != NULL) { if (w == 0) { - // if we're currently at zero, we need to record the edge start point + /* if we're currently at zero, we need to record the edge start point */ x0 = e->x; w += e->dir; } else { int x1 = e->x; w += e->dir; - // if we went to zero, we need to draw + /* if we went to zero, we need to draw */ if (w == 0) nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); } e = e->next; } } else if (fillRule == NSVG_FILLRULE_EVENODD) { - // Even-odd + /* Even-odd */ while (e != NULL) { if (w == 0) { - // if we're currently at zero, we need to record the edge start point + /* if we're currently at zero, we need to record the edge start point */ x0 = e->x; w = 1; } else { int x1 = e->x; w = 0; nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax); } @@ -1011,16 +1013,16 @@ for (i = 0; i < count; i++) { int r,g,b; int a = nsvg__div255((int)cover[0] * ca); int ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); a += nsvg__div255(ia * (int)dst[3]); @@ -1031,12 +1033,12 @@ cover++; dst += 4; } } else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. + /* TODO: spread modes. */ + /* TODO: plenty of opportunities to optimize. */ float fx, fy, dx, gy; float* t = cache->xform; int i, cr, cg, cb, ca; unsigned int c; @@ -1054,16 +1056,16 @@ ca = (c >> 24) & 0xff; a = nsvg__div255((int)cover[0] * ca); ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); a += nsvg__div255(ia * (int)dst[3]); @@ -1075,13 +1077,13 @@ cover++; dst += 4; fx += dx; } } else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) { - // TODO: spread modes. - // TODO: plenty of opportunities to optimize. - // TODO: focus (fx,fy) + /* TODO: spread modes. */ + /* TODO: plenty of opportunities to optimize. */ + /* TODO: focus (fx,fy) */ float fx, fy, dx, gx, gy, gd; float* t = cache->xform; int i, cr, cg, cb, ca; unsigned int c; @@ -1101,16 +1103,16 @@ ca = (c >> 24) & 0xff; a = nsvg__div255((int)cover[0] * ca); ia = 255 - a; - // Premultiply + /* Premultiply */ r = nsvg__div255(cr * a); g = nsvg__div255(cg * a); b = nsvg__div255(cb * a); - // Blend over + /* Blend over */ r += nsvg__div255(ia * (int)dst[0]); g += nsvg__div255(ia * (int)dst[1]); b += nsvg__div255(ia * (int)dst[2]); a += nsvg__div255(ia * (int)dst[3]); @@ -1129,37 +1131,37 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule) { NSVGactiveEdge *active = NULL; int y, s; int e = 0; - int maxWeight = (255 / NSVG__SUBSAMPLES); // weight per vertical scanline + int maxWeight = (255 / NSVG__SUBSAMPLES); /* weight per vertical scanline */ int xmin, xmax; for (y = 0; y < r->height; y++) { memset(r->scanline, 0, r->width); xmin = r->width; xmax = 0; for (s = 0; s < NSVG__SUBSAMPLES; ++s) { - // find center of pixel for this scanline + /* find center of pixel for this scanline */ float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; NSVGactiveEdge **step = &active; - // update all active edges; - // remove all active edges that terminate before the center of this scanline + /* update all active edges; */ + /* remove all active edges that terminate before the center of this scanline */ while (*step) { NSVGactiveEdge *z = *step; if (z->ey <= scany) { - *step = z->next; // delete from list -// NSVG__assert(z->valid); + *step = z->next; /* delete from list */ +/* NSVG__assert(z->valid); */ nsvg__freeActive(r, z); } else { - z->x += z->dx; // advance to position for current scanline - step = &((*step)->next); // advance through list + z->x += z->dx; /* advance to position for current scanline */ + step = &((*step)->next); /* advance through list */ } } - // resort the list if needed + /* resort the list if needed */ for (;;) { int changed = 0; step = &active; while (*step && (*step)->next) { if ((*step)->x > (*step)->next->x) { @@ -1173,40 +1175,40 @@ step = &(*step)->next; } if (!changed) break; } - // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline + /* insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */ while (e < r->nedges && r->edges[e].y0 <= scany) { if (r->edges[e].y1 > scany) { NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany); if (z == NULL) break; - // find insertion point + /* find insertion point */ if (active == NULL) { active = z; } else if (z->x < active->x) { - // insert at front + /* insert at front */ z->next = active; active = z; } else { - // find thing to insert AFTER + /* find thing to insert AFTER */ NSVGactiveEdge* p = active; while (p->next && p->next->x < z->x) p = p->next; - // at this point, p->next->x is NOT < z->x + /* at this point, p->next->x is NOT < z->x */ z->next = p->next; p->next = z; } } e++; } - // now process all active edges in non-zero fashion + /* now process all active edges in non-zero fashion */ if (active != NULL) nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule); } - // Blit + /* Blit */ if (xmin < 0) xmin = 0; if (xmax > r->width-1) xmax = r->width-1; if (xmin <= xmax) { nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache); } @@ -1216,11 +1218,11 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride) { int x,y; - // Unpremultiply + /* Unpremultiply */ for (y = 0; y < h; y++) { unsigned char *row = &image[y*stride]; for (x = 0; x < w; x++) { int r = row[0], g = row[1], b = row[2], a = row[3]; if (a != 0) { @@ -1230,11 +1232,11 @@ } row += 4; } } - // Defringe + /* Defringe */ for (y = 0; y < h; y++) { unsigned char *row = &image[y*stride]; for (x = 0; x < w; x++) { int r = 0, g = 0, b = 0, a = row[3], n = 0; if (a == 0) { @@ -1409,23 +1411,23 @@ r->freelist = NULL; r->nedges = 0; nsvg__flattenShape(r, shape, scale); - // Scale and translate edges + /* Scale and translate edges */ for (i = 0; i < r->nedges; i++) { e = &r->edges[i]; e->x0 = tx + e->x0; e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; e->x1 = tx + e->x1; e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; } - // Rasterize edges + /* Rasterize edges */ qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + /* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */ nsvg__initPaint(&cache, &shape->fill, shape->opacity); nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule); } if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) { @@ -1433,25 +1435,25 @@ r->freelist = NULL; r->nedges = 0; nsvg__flattenShapeStroke(r, shape, scale); -// dumpEdges(r, "edge.svg"); +/* dumpEdges(r, "edge.svg"); */ - // Scale and translate edges + /* Scale and translate edges */ for (i = 0; i < r->nedges; i++) { e = &r->edges[i]; e->x0 = tx + e->x0; e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES; e->x1 = tx + e->x1; e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES; } - // Rasterize edges + /* Rasterize edges */ qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge); - // now, traverse the scanlines and find the intersections on each scanline, use non-zero rule + /* now, traverse the scanlines and find the intersections on each scanline, use non-zero rule */ nsvg__initPaint(&cache, &shape->stroke, shape->opacity); nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO); } } Index: generic/tk.decls ================================================================== --- generic/tk.decls +++ generic/tk.decls @@ -3,12 +3,12 @@ # This file contains the declarations for all supported public # functions that are exported by the Tk library via the stubs table. # This file is used to generate the tkDecls.h, tkPlatDecls.h, # tkStub.c, and tkPlatStub.c files. # -# Copyright (c) 1998-2000 Ajuba Solutions. -# Copyright (c) 2007 Daniel A. Steffen +# Copyright © 1998-2000 Ajuba Solutions. +# Copyright © 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tk @@ -1088,10 +1088,16 @@ Tcl_Obj *detail) } declare 279 { Tcl_Obj *Tk_FontGetDescription(Tk_Font tkfont) } + +# TIP#529 +declare 280 { + void Tk_CreatePhotoImageFormatVersion3( + const Tk_PhotoImageFormatVersion3 *formatPtr) +} # Define the platform specific public Tk interface. These functions are # only available on the designated platform. interface tkPlat Index: generic/tk.h ================================================================== --- generic/tk.h +++ generic/tk.h @@ -66,14 +66,14 @@ */ #define TK_MAJOR_VERSION 8 #define TK_MINOR_VERSION 7 #define TK_RELEASE_LEVEL TCL_ALPHA_RELEASE -#define TK_RELEASE_SERIAL 4 +#define TK_RELEASE_SERIAL 6 #define TK_VERSION "8.7" -#define TK_PATCH_LEVEL "8.7a4" +#define TK_PATCH_LEVEL "8.7a6" /* * A special definition used to allow this header file to be included from * windows or mac resource files so that they can obtain version information. * RC_INVOKED is defined by default by the windows RC tool and manually set @@ -92,14 +92,11 @@ # include # ifdef MAC_OSX_TK # include # endif #endif -#if defined(STDC_HEADERS) || defined(__STDC__) || defined(__C99__FUNC__) \ - || defined(__cplusplus) || defined(_MSC_VER) || defined(__ICC) -# include -#endif +#include #ifdef BUILD_tk #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT #else @@ -169,11 +166,12 @@ TK_OPTION_SYNONYM, TK_OPTION_PIXELS, TK_OPTION_WINDOW, TK_OPTION_END, TK_OPTION_CUSTOM, - TK_OPTION_STYLE + TK_OPTION_STYLE, + TK_OPTION_INDEX } Tk_OptionType; /* * Structures of the following type are used by widgets to specify their * configuration options. Typically each widget has a static array of these @@ -1435,10 +1433,40 @@ typedef int (Tk_ImageFileWriteProc) (Tcl_Interp *interp, const char *fileName, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); typedef int (Tk_ImageStringWriteProc) (Tcl_Interp *interp, Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); #endif /* USE_OLD_IMAGE */ + +/* + * The following alternate definitions are used with the Tk8.7 file format + * supporting a metadata dict, internal dstring and close file flag + */ + +typedef struct Tk_PhotoImageFormatVersion3 Tk_PhotoImageFormatVersion3; +typedef int (Tk_ImageFileMatchProcVersion3) (Tcl_Interp *interp, + Tcl_Channel chan, const char *fileName, Tcl_Obj *format, + Tcl_Obj *metadataIn, int *widthPtr, int *heightPtr, + Tcl_Obj *metadataOut); +typedef int (Tk_ImageStringMatchProcVersion3) (Tcl_Interp *interp, + Tcl_Obj *dataObj, Tcl_Obj *format, Tcl_Obj *metadataIn, int *widthPtr, + int *heightPtr, Tcl_Obj *metadataOut); +typedef int (Tk_ImageFileReadProcVersion3) (Tcl_Interp *interp, + Tcl_Channel chan, + const char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn, + Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, int srcX, int srcY, + Tcl_Obj *metadataOut); +typedef int (Tk_ImageStringReadProcVersion3) (Tcl_Interp *interp, + Tcl_Obj *dataObj, Tcl_Obj *format, Tcl_Obj *metadataIn, + Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, + int srcX, int srcY, Tcl_Obj *metadataOut); +typedef int (Tk_ImageFileWriteProcVersion3) (Tcl_Interp *interp, + const char *fileName, Tcl_Obj *format, Tcl_Obj *metadataIn, + Tk_PhotoImageBlock *blockPtr); +typedef int (Tk_ImageStringWriteProcVersion3) (Tcl_Interp *interp, + Tcl_Obj *format, Tcl_Obj *metadataIn, Tk_PhotoImageBlock *blockPtr); + /* * The following structure represents a particular file format for storing * images (e.g., PPM, GIF, JPEG, etc.). It provides information to allow image * files of that format to be recognized and read into a photo image. @@ -1468,10 +1496,42 @@ struct Tk_PhotoImageFormat *nextPtr; /* Next in list of all photo image formats * currently known. Filled in by Tk, not by * image format handler. */ }; + +/* + * The following structure is the same plus added support for the metadata + * structure. + */ + +struct Tk_PhotoImageFormatVersion3 { + const char *name; /* Name of image file format */ + Tk_ImageFileMatchProcVersion3 *fileMatchProc; + /* Procedure to call to determine whether an + * image file matches this format. */ + Tk_ImageStringMatchProcVersion3 *stringMatchProc; + /* Procedure to call to determine whether the + * data in a string matches this format. */ + Tk_ImageFileReadProcVersion3 *fileReadProc; + /* Procedure to call to read data from an + * image file into a photo image. */ + Tk_ImageStringReadProcVersion3 *stringReadProc; + /* Procedure to call to read data from a + * string into a photo image. */ + Tk_ImageFileWriteProcVersion3 *fileWriteProc; + /* Procedure to call to write data from a + * photo image to a file. */ + Tk_ImageStringWriteProcVersion3 *stringWriteProc; + /* Procedure to call to obtain a string + * representation of the data in a photo + * image.*/ + struct Tk_PhotoImageFormatVersion3 *nextPtr; + /* Next in list of all photo image formats + * currently known. Filled in by Tk, not by + * image format handler. */ +}; /* *---------------------------------------------------------------------- * * Procedure prototypes and structures used for managing styles: Index: generic/tk3d.c ================================================================== --- generic/tk3d.c +++ generic/tk3d.c @@ -2,12 +2,12 @@ * tk3d.c -- * * This module provides procedures to draw borders in the * three-dimensional Motif style. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tk3d.h ================================================================== --- generic/tk3d.h +++ generic/tk3d.h @@ -1,11 +1,11 @@ /* * tk3d.h -- * * Declarations of types and functions shared by the 3d border module. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkArgv.c ================================================================== --- generic/tkArgv.c +++ generic/tkArgv.c @@ -2,12 +2,12 @@ * tkArgv.c -- * * This file contains a function that handles table-based argv-argc * parsing. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkArray.h ================================================================== --- generic/tkArray.h +++ generic/tkArray.h @@ -3,11 +3,11 @@ * * An array is a sequence of items, stored in a contiguous memory region. * Random access to any item is very fast. New items can be either appended * or prepended. An array may be traversed in the forward or backward direction. * - * Copyright (c) 2018-2019 by Gregor Cramer. + * Copyright © 2018-2019 Gregor Cramer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkAtom.c ================================================================== --- generic/tkAtom.c +++ generic/tkAtom.c @@ -4,12 +4,12 @@ * This file manages a cache of X Atoms in order to avoid interactions * with the X server. It's much like the Xmu routines, except it has a * cleaner interface (caller doesn't have to provide permanent storage * for atom names, for example). * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkBind.c ================================================================== --- generic/tkBind.c +++ generic/tkBind.c @@ -2,14 +2,14 @@ * tkBind.c -- * * This file provides functions that associate Tcl commands with X events * or sequences of X events. * - * Copyright (c) 1989-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. - * Copyright (c) 2018-2019 by Gregor Cramer. + * Copyright © 1989-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998 Scriptics Corporation. + * Copyright © 2018-2019 Gregor Cramer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -430,11 +430,13 @@ static const ModInfo modArray[] = { {"Control", ControlMask, 0}, {"Shift", ShiftMask, 0}, {"Lock", LockMask, 0}, {"Meta", META_MASK, 0}, +#ifndef TK_NO_DEPRECATED {"M", META_MASK, 0}, +#endif {"Alt", ALT_MASK, 0}, {"Extended", EXTENDED_MASK, 0}, {"B1", Button1Mask, 0}, {"Button1", Button1Mask, 0}, {"B2", Button2Mask, 0}, @@ -453,14 +455,24 @@ {"Button8", Button8Mask, 0}, {"B9", Button9Mask, 0}, {"Button9", Button9Mask, 0}, {"Mod1", Mod1Mask, 0}, {"M1", Mod1Mask, 0}, +#ifdef MAC_OSX_TK {"Command", Mod1Mask, 0}, +#elif defined (_WIN32) + {"Command", ControlMask, 0}, +#else + {"Command", META_MASK, 0}, +#endif {"Mod2", Mod2Mask, 0}, {"M2", Mod2Mask, 0}, +#ifdef MAC_OSX_TK {"Option", Mod2Mask, 0}, +#else + {"Option", ALT_MASK, 0}, +#endif {"Mod3", Mod3Mask, 0}, {"M3", Mod3Mask, 0}, {"Mod4", Mod4Mask, 0}, {"M4", Mod4Mask, 0}, {"Mod5", Mod5Mask, 0}, @@ -492,14 +504,18 @@ * unless you've asked about button events. */ static const EventInfo eventArray[] = { {"Key", KeyPress, KeyPressMask}, +#ifndef TK_NO_DEPRECATED {"KeyPress", KeyPress, KeyPressMask}, +#endif {"KeyRelease", KeyRelease, KeyPressMask|KeyReleaseMask}, {"Button", ButtonPress, ButtonPressMask}, +#ifndef TK_NO_DEPRECATED {"ButtonPress", ButtonPress, ButtonPressMask}, +#endif {"ButtonRelease", ButtonRelease, ButtonPressMask|ButtonReleaseMask}, {"Motion", MotionNotify, ButtonPressMask|PointerMotionMask}, {"Enter", EnterNotify, EnterWindowMask}, {"Leave", LeaveNotify, LeaveWindowMask}, {"FocusIn", FocusIn, FocusChangeMask}, @@ -800,10 +816,11 @@ static Time CurrentTimeInMilliSecs(void) { Tcl_Time now; + Tcl_GetTime(&now); return ((Time) now.sec)*1000 + ((Time) now.usec)/1000; } static Info @@ -2992,12 +3009,12 @@ } while (1) { char numStorage[TCL_INTEGER_SPACE]; const char *string; - Tcl_WideInt number; /* signed */ - Tcl_WideUInt unumber; /* unsigned */ + long long number; /* signed */ + unsigned long long unumber; /* unsigned */ /* * Find everything up to the next % character and append it to the * result string. */ @@ -5238,18 +5255,52 @@ KeySym TkStringToKeysym( const char *name) /* Name of a keysym. */ { #ifdef REDO_KEYSYM_LOOKUP - Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&keySymTable, name); + Tcl_HashEntry *hPtr; +#endif /* REDO_KEYSYM_LOOKUP */ + int keysym; + size_t len = TkUtfToUniChar(name, &keysym); + if (name[len] == '\0') { + if (!Tcl_UniCharIsPrint(keysym)) { + /* This form not supported */ + } else if ((unsigned)(keysym - 0x21) <= 0x5D) { + return keysym; + } else if ((unsigned)(keysym - 0xA1) <= 0x5E) { + return keysym; + } else if (keysym == 0x20AC) { + return 0x20AC; + } else { + return keysym + 0x1000000; + } + } +#ifdef REDO_KEYSYM_LOOKUP + if ((name[0] == 'U') && ((unsigned)(name[1] - '0') <= 9)) { + char *p = (char *)name + 1; + keysym = strtol(p, &p, 16); + if ((p >= name + 5) && (p <= name + 9) && !*p && (keysym >= 0x20) + && ((unsigned)(keysym - 0x7F) > 0x20)) { + if ((unsigned)(keysym - 0x21) <= 0x5D) { + return keysym; + } else if ((unsigned)(keysym - 0xA1) <= 0x5E) { + return keysym; + } else if (keysym == 0x20AC) { + return keysym; + } + return keysym + 0x1000000; + } + } +#endif +#ifdef REDO_KEYSYM_LOOKUP + hPtr = Tcl_FindHashEntry(&keySymTable, name); if (hPtr) { return (KeySym) Tcl_GetHashValue(hPtr); } - assert(name); - if (strlen(name) == 1u) { - KeySym keysym = (KeySym) (unsigned char) name[0]; + if (((unsigned)(name[0]-1) < 0x7F) && !name[1]) { + keysym = (unsigned char) name[0]; if (TkKeysymToString(keysym)) { return keysym; } } @@ -5278,20 +5329,41 @@ const char * TkKeysymToString( KeySym keysym) { #ifdef REDO_KEYSYM_LOOKUP - Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym); + Tcl_HashEntry *hPtr; +#endif + + if ((unsigned)(keysym - 0x21) <= 0x5D) { + keysym += 0x1000000; + } else if ((unsigned)(keysym - 0xA1) <= 0x5E) { + keysym += 0x1000000; + } else if (keysym == 0x20AC) { + keysym += 0x1000000; + } + if ((keysym >= 0x1000020) && (keysym <= 0x110FFFF) + && ((unsigned)(keysym - 0x100007F) > 0x20)) { + char buf[10]; + if (Tcl_UniCharIsPrint(keysym-0x1000000)) { + buf[TkUniCharToUtf(keysym - 0x1000000, buf)] = '\0'; + } else if (keysym >= 0x1010000) { + sprintf(buf, "U%08X", (int)(keysym - 0x1000000)); + } else { + sprintf(buf, "U%04X", (int)(keysym - 0x1000000)); + } + return Tk_GetUid(buf); + } + +#ifdef REDO_KEYSYM_LOOKUP + hPtr = Tcl_FindHashEntry(&nameTable, INT2PTR(keysym)); if (hPtr) { return (const char *)Tcl_GetHashValue(hPtr); } #endif /* REDO_KEYSYM_LOOKUP */ - if (keysym > (KeySym)0x1008FFFF) { - return NULL; - } return XKeysymToString(keysym); } /* *---------------------------------------------------------------------- Index: generic/tkBitmap.c ================================================================== --- generic/tkBitmap.c +++ generic/tkBitmap.c @@ -3,12 +3,12 @@ * * This file maintains a database of read-only bitmaps for the Tk * toolkit. This allows bitmaps to be shared between widgets and also * avoids interactions with the X server. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkButton.c ================================================================== --- generic/tkButton.c +++ generic/tkButton.c @@ -3,12 +3,12 @@ * * This module implements a collection of button-like widgets for the Tk * toolkit. The widgets implemented include buttons, checkbuttons, * radiobuttons, and labels. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -141,12 +141,12 @@ {TK_OPTION_STRING, "-text", "text", "Text", DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0}, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(TkButton, underline), 0}, {TK_OPTION_STRING, "-width", "width", "Width", DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), offsetof(TkButton, wrapLength), 0, 0, 0}, @@ -242,12 +242,12 @@ {TK_OPTION_STRING, "-text", "text", "Text", DEF_BUTTON_TEXT, offsetof(TkButton, textPtr), TCL_INDEX_NONE, 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_BUTTON_TEXT_VARIABLE, offsetof(TkButton, textVarNamePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0}, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(TkButton, underline), 0}, {TK_OPTION_STRING, "-width", "width", "Width", DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_BUTTON_WRAP_LENGTH, offsetof(TkButton, wrapLengthPtr), offsetof(TkButton, wrapLength), 0, 0, 0}, @@ -352,12 +352,12 @@ {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", DEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0}, - {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0}, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(TkButton, underline), 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", DEF_CHECKBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-width", "width", "Width", DEF_BUTTON_WIDTH, offsetof(TkButton, widthPtr), TCL_INDEX_NONE, 0, 0, 0}, @@ -462,12 +462,12 @@ {TK_OPTION_STRING, "-tristateimage", "tristateImage", "TristateImage", DEF_BUTTON_IMAGE, offsetof(TkButton, tristateImagePtr), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, 0}, {TK_OPTION_STRING, "-tristatevalue", "tristateValue", "TristateValue", DEF_BUTTON_TRISTATE_VALUE, offsetof(TkButton, tristateValuePtr), TCL_INDEX_NONE, 0, 0, 0}, - {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_BUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkButton, underline), 0, 0, 0}, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(TkButton, underline), 0}, {TK_OPTION_STRING, "-value", "value", "Value", DEF_BUTTON_VALUE, offsetof(TkButton, onValuePtr), TCL_INDEX_NONE, 0, 0, 0}, {TK_OPTION_STRING, "-variable", "variable", "Variable", DEF_RADIOBUTTON_VARIABLE, offsetof(TkButton, selVarNamePtr), TCL_INDEX_NONE, 0, 0, 0}, @@ -685,11 +685,11 @@ butPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(tkwin), ButtonWidgetObjCmd, butPtr, ButtonCmdDeletedProc); butPtr->type = type; butPtr->optionTable = optionTable; butPtr->textPtr = NULL; - butPtr->underline = -1; + butPtr->underline = INT_MIN; butPtr->textVarNamePtr = NULL; butPtr->bitmap = None; butPtr->imagePtr = NULL; butPtr->image = NULL; butPtr->selectImagePtr = NULL; Index: generic/tkButton.h ================================================================== --- generic/tkButton.h +++ generic/tkButton.h @@ -2,11 +2,11 @@ * tkButton.h -- * * Declarations of types and functions used to implement button-like * widgets. * - * Copyright (c) 1996-1998 by Sun Microsystems, Inc. + * Copyright © 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -65,11 +65,11 @@ */ Tcl_Obj *textPtr; /* Value of -text option: specifies text to * display in button. */ int underline; /* Value of -underline option: specifies index - * of character to underline. < 0 means don't + * of character to underline. INT_MIN means don't * underline anything. */ Tcl_Obj *textVarNamePtr; /* Value of -textvariable option: specifies * name of variable or NULL. If non-NULL, * button displays the contents of this * variable. */ Index: generic/tkCanvArc.c ================================================================== --- generic/tkCanvArc.c +++ generic/tkCanvArc.c @@ -1,12 +1,12 @@ /* * tkCanvArc.c -- * * This file implements arc items for canvas widgets. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCanvBmap.c ================================================================== --- generic/tkCanvBmap.c +++ generic/tkCanvBmap.c @@ -1,12 +1,12 @@ /* * tkCanvBmap.c -- * * This file implements bitmap items for canvas widgets. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCanvImg.c ================================================================== --- generic/tkCanvImg.c +++ generic/tkCanvImg.c @@ -1,12 +1,12 @@ /* * tkCanvImg.c -- * * This file implements image items for canvas widgets. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCanvLine.c ================================================================== --- generic/tkCanvLine.c +++ generic/tkCanvLine.c @@ -1,13 +1,13 @@ /* * tkCanvLine.c -- * * This file implements line items for canvas widgets. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1746,11 +1746,11 @@ TkSizeT idx, length; LineItem *linePtr = (LineItem *) itemPtr; const char *string; (void)canvas; - if (TCL_OK == TkGetIntForIndex(obj, 2*linePtr->numPoints - 1, 0, &idx)) { + if (TCL_OK == TkGetIntForIndex(obj, 2*linePtr->numPoints - 1, 1, &idx)) { if (idx == TCL_INDEX_NONE) { idx = 0; } else if (idx > (2*(TkSizeT)linePtr->numPoints)) { idx = 2*linePtr->numPoints; } else { @@ -1758,11 +1758,11 @@ } *indexPtr = idx; return TCL_OK; } - string = TkGetStringFromObj(obj, &length); + string = Tcl_GetStringFromObj(obj, &length); if (string[0] == '@') { int i; double x, y, bestDist, dist, *coordPtr; char *end; Index: generic/tkCanvPoly.c ================================================================== --- generic/tkCanvPoly.c +++ generic/tkCanvPoly.c @@ -1,13 +1,13 @@ /* * tkCanvPoly.c -- * * This file implements polygon items for canvas widgets. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Ajuba Solutions. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1681,18 +1681,20 @@ TkSizeT count = 2*(polyPtr->numPoints - polyPtr->autoClosed); if (TCL_OK == TkGetIntForIndex(obj, (INT_MAX - 1) - ((INT_MAX) % count), 1, &idx)) { if (idx == TCL_INDEX_NONE) { idx = 0; + } else if (idx >= INT_MAX - ((INT_MAX) % count)) { + idx = count; } else { idx = (idx & (TkSizeT)-2) % count; } *indexPtr = idx; return TCL_OK; } - string = TkGetStringFromObj(obj, &length); + string = Tcl_GetStringFromObj(obj, &length); if (string[0] == '@') { int i; double x, y, bestDist, dist, *coordPtr; char *end; Index: generic/tkCanvPs.c ================================================================== --- generic/tkCanvPs.c +++ generic/tkCanvPs.c @@ -3,12 +3,12 @@ * * This module provides Postscript output support for canvases, including * the "postscript" widget command plus a few utility functions used for * generating Postscript. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCanvText.c ================================================================== --- generic/tkCanvText.c +++ generic/tkCanvText.c @@ -1,12 +1,12 @@ /* * tkCanvText.c -- * * This file implements text items for canvas widgets. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -51,11 +51,11 @@ Pixmap disabledStipple; /* Stipple bitmap for text, or None. */ char *text; /* Text for item (malloc-ed). */ int width; /* Width of lines for word-wrap, pixels. Zero * means no word-wrap. */ int underline; /* Index of character to put underline beneath - * or -1 for no underlining. */ + * or INT_MIN for no underlining. */ double angle; /* What angle, in degrees, to draw the text * at. */ /* * Fields whose values are derived from the current values of the @@ -90,10 +90,99 @@ TkCanvasTagsParseProc, TkCanvasTagsPrintProc, NULL }; static const Tk_CustomOption offsetOption = { TkOffsetParseProc, TkOffsetPrintProc, INT2PTR(TK_OFFSET_RELATIVE) }; + +static int +UnderlineParseProc( + ClientData dummy, /* Not used.*/ + Tcl_Interp *interp, /* Used for reporting errors. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + const char *value, /* Value of option. */ + char *widgRec, /* Pointer to record for item. */ + TkSizeT offset) /* Offset into item (ignored). */ +{ + int *underlinePtr = (int *) (widgRec + offset); + Tcl_Obj obj; + int code; + TkSizeT underline; + (void)dummy; + (void)tkwin; + + if (value == NULL || *value == 0) { + *underlinePtr = INT_MIN; /* No underline */ + return TCL_OK; + } + + obj.refCount = 1; + obj.bytes = (char *)value; + obj.length = strlen(value); + obj.typePtr = NULL; + code = TkGetIntForIndex(&obj, TCL_INDEX_END, 0, &underline); + if (code == TCL_OK) { + if (underline == TCL_INDEX_NONE) { + underline = INT_MIN; + } else if ((size_t)underline > (size_t)TCL_INDEX_END>>1) { + underline++; + } else if (underline >= INT_MAX) { + underline = INT_MAX; + } + *underlinePtr = underline; + + } else { + Tcl_AppendResult(interp, "bad index \"", value, + "\": must be integer?[+-]integer? or end?[+-]integer?", NULL); + } + return code; +} + +const char * +UnderlinePrintProc( + ClientData dummy, /* Ignored. */ + Tk_Window tkwin, /* Window containing canvas widget. */ + char *widgRec, /* Pointer to record for item. */ + TkSizeT offset, /* Pointer to record for item. */ + Tcl_FreeProc **freeProcPtr) /* Pointer to variable to fill in with + * information about how to reclaim storage + * for return string. */ +{ + int underline = *(int *)(widgRec + offset); + char *p; + (void)dummy; + (void)tkwin; + + if (underline == INT_MIN) { +#if !defined(TK_NO_DEPRECATED) && TK_MAJOR_VERSION < 9 + p = (char *)"-1"; +#else + p = (char *)""; +#endif + *freeProcPtr = TCL_STATIC; + return p; + } else if (underline == INT_MAX) { + p = (char *)"end+1"; + *freeProcPtr = TCL_STATIC; + return p; + } else if (underline == -1) { + p = (char *)"end"; + *freeProcPtr = TCL_STATIC; + return p; + } + p = (char *)ckalloc(32); + if (underline < 0) { + sprintf(p, "end%d", underline); + } else { + sprintf(p, "%d", underline); + } + *freeProcPtr = TCL_DYNAMIC; + return p; +} + +static const Tk_CustomOption underlineOption = { + UnderlineParseProc, UnderlinePrintProc, NULL +}; static const Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_COLOR, "-activefill", NULL, NULL, NULL, offsetof(TextItem, activeColor), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_BITMAP, "-activestipple", NULL, NULL, @@ -121,12 +210,12 @@ NULL, offsetof(TextItem, stipple), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tags", NULL, NULL, NULL, 0, TK_CONFIG_NULL_OK, &tagsOption}, {TK_CONFIG_STRING, "-text", NULL, NULL, "", offsetof(TextItem, text), 0, NULL}, - {TK_CONFIG_INT, "-underline", NULL, NULL, - "-1", offsetof(TextItem, underline), 0, NULL}, + {TK_CONFIG_CUSTOM, "-underline", NULL, NULL, NULL, + offsetof(TextItem, underline), TK_CONFIG_NULL_OK, &underlineOption}, {TK_CONFIG_PIXELS, "-width", NULL, NULL, "0", offsetof(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT, NULL}, {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; @@ -262,11 +351,11 @@ textPtr->stipple = None; textPtr->activeStipple = None; textPtr->disabledStipple = None; textPtr->text = NULL; textPtr->width = 0; - textPtr->underline = -1; + textPtr->underline = INT_MIN; textPtr->angle = 0.0; textPtr->numChars = 0; textPtr->numBytes = 0; textPtr->textLayout = NULL; @@ -1018,11 +1107,11 @@ TkSizeT byteCount; char *newStr, *text; const char *string; Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr; - string = TkGetStringFromObj(obj, &byteCount); + string = Tcl_GetStringFromObj(obj, &byteCount); text = textPtr->text; if (index == TCL_INDEX_NONE) { index = 0; @@ -1397,11 +1486,11 @@ } *indexPtr = idx; return TCL_OK; } - string = TkGetStringFromObj(obj, &length); + string = Tcl_GetStringFromObj(obj, &length); c = string[0]; if ((c == 'i') && (strncmp(string, "insert", length) == 0)) { *indexPtr = textPtr->insertPos; Index: generic/tkCanvUtil.c ================================================================== --- generic/tkCanvUtil.c +++ generic/tkCanvUtil.c @@ -2,11 +2,11 @@ * tkCanvUtil.c -- * * This file contains a collection of utility functions used by the * implementations of various canvas item types. * - * Copyright (c) 1994 Sun Microsystems, Inc. + * Copyright © 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -772,11 +772,11 @@ if (methods == NULL) { methods = InitSmoothMethods(interp); } /* - * Backward compatability hack. + * Backward compatibility hack. */ if (strncmp(value, "bezier", length) == 0) { smooth = &tkBezierSmoothMethod; } Index: generic/tkCanvWind.c ================================================================== --- generic/tkCanvWind.c +++ generic/tkCanvWind.c @@ -1,12 +1,12 @@ /* * tkCanvWind.c -- * * This file implements window items for canvas widgets. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCanvas.c ================================================================== --- generic/tkCanvas.c +++ generic/tkCanvas.c @@ -3,26 +3,25 @@ * * This module implements canvas widgets for the Tk toolkit. A canvas * displays a background and a collection of graphical objects such as * rectangles, lines, and texts. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tkInt.h" #include "tkCanvas.h" #include "default.h" -#ifdef TK_NO_DOUBLE_BUFFERING +#include "tkPort.h" #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif -#endif /* TK_NO_DOUBLE_BUFFERING */ /* * See tkCanvas.h for key data structures used to implement canvases. */ @@ -1255,11 +1254,11 @@ if (objc < 3) { Tcl_WrongNumArgs(interp, 2, objv, "type coords ?arg ...?"); result = TCL_ERROR; goto done; } - arg = TkGetStringFromObj(objv[2], &length); + arg = Tcl_GetStringFromObj(objv[2], &length); c = arg[0]; /* * Lock because the list of types is a global resource that could be * updated by another thread. That's fairly unlikely, but not @@ -2806,14 +2805,23 @@ blockPtr.width = cWidth; blockPtr.height = cHeight; blockPtr.pixelSize = 4; blockPtr.pitch = blockPtr.pixelSize * blockPtr.width; + +#ifdef TK_XGETIMAGE_USES_ABGR32 + blockPtr.offset[0] = 1; + blockPtr.offset[1] = 2; + blockPtr.offset[2] = 3; + blockPtr.offset[3] = 0; +#else blockPtr.offset[0] = 0; blockPtr.offset[1] = 1; blockPtr.offset[2] = 2; blockPtr.offset[3] = 3; +#endif + blockPtr.pixelPtr = (unsigned char *)ckalloc(blockPtr.pixelSize * blockPtr.height * blockPtr.width); /* * Now convert the image data pixel by pixel from XImage to 32bit RGBA * format suitable for Tk_PhotoPutBlock(). @@ -2846,11 +2854,11 @@ Tcl_AppendResult(interp, " {", NULL); #endif for(x = 0; x < blockPtr.width; ++x) { unsigned int pixel = 0; - + int pixel_offset = blockPtr.pitch * y + blockPtr.pixelSize * x; switch (ximagePtr->bits_per_pixel) { /* * Get an 8 bit pixel from the XImage. */ @@ -2899,25 +2907,49 @@ * If the visual mask was correct there would be no need to * swap anything here. */ #ifdef _WIN32 -#define R_OFFSET 2 -#define B_OFFSET 0 +#define R_OFFSET blockPtr.offset[2] +#define G_OFFSET blockPtr.offset[1] +#define B_OFFSET blockPtr.offset[0] +#define A_OFFSET blockPtr.offset[3] +#else +#define R_OFFSET blockPtr.offset[0] +#define G_OFFSET blockPtr.offset[1] +#define B_OFFSET blockPtr.offset[2] +#define A_OFFSET blockPtr.offset[3] +#endif +#ifdef TK_XGETIMAGE_USES_ABGR32 +#define COPY_PIXEL (ximagePtr->bits_per_pixel == 32) #else -#define R_OFFSET 0 -#define B_OFFSET 2 +#define COPY_PIXEL 0 #endif - blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + R_OFFSET] = + + if (COPY_PIXEL) { + /* + * This platform packs pixels in RGBA byte order, as expected + * by Tk_PhotoPutBlock() so we can just copy the pixel as an int. + */ + *((unsigned int *) (blockPtr.pixelPtr + pixel_offset)) = pixel; + } else { + blockPtr.pixelPtr[pixel_offset + R_OFFSET] = (unsigned char)((pixel & visualPtr->red_mask) >> rshift); - blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +1] = + blockPtr.pixelPtr[pixel_offset + G_OFFSET] = (unsigned char)((pixel & visualPtr->green_mask) >> gshift); - blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x + B_OFFSET] = + blockPtr.pixelPtr[pixel_offset + B_OFFSET] = (unsigned char)((pixel & visualPtr->blue_mask) >> bshift); - blockPtr.pixelPtr[blockPtr.pitch * y + blockPtr.pixelSize * x +3] = 0xFF; + blockPtr.pixelPtr[pixel_offset + A_OFFSET] = 0xFF; + } #ifdef DEBUG_DRAWCANVAS + fprintf(stderr, "Converted pixel %x to %hhx %hhx %hhx %hhx \n", + pixel, + blockPtr.pixelPtr[pixel_offset + 0], + blockPtr.pixelPtr[pixel_offset + 1], + blockPtr.pixelPtr[pixel_offset + 2], + blockPtr.pixelPtr[pixel_offset + 3]); { int ix; if (x > 0) Tcl_AppendResult(interp, "-", NULL); for (ix = 0; ix < 4; ++ix) { @@ -3002,10 +3034,14 @@ TkCanvas *canvasPtr = (TkCanvas *)clientData; Tk_Window tkwin = canvasPtr->tkwin; Tk_Item *itemPtr; Pixmap pixmap; int screenX1, screenX2, screenY1, screenY2, width, height; +#ifdef MAC_OSX_TK + TkWindow *winPtr; + MacDrawable *macWin; +#endif if (canvasPtr->tkwin == NULL) { return; } @@ -3016,12 +3052,12 @@ #ifdef MAC_OSX_TK /* * If drawing is disabled, all we need to do is * clear the REDRAW_PENDING flag. */ - TkWindow *winPtr = (TkWindow *)(canvasPtr->tkwin); - MacDrawable *macWin = winPtr->privatePtr; + winPtr = (TkWindow *)(canvasPtr->tkwin); + macWin = winPtr->privatePtr; if (macWin && (macWin->flags & TK_DO_NOT_DRAW)){ canvasPtr->flags &= ~REDRAW_PENDING; return; } #endif Index: generic/tkCanvas.h ================================================================== --- generic/tkCanvas.h +++ generic/tkCanvas.h @@ -1,13 +1,13 @@ /* * tkCanvas.h -- * * Declarations shared among all the files that implement canvas widgets. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1995 Sun Microsystems, Inc. + * Copyright © 1998 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkClipboard.c ================================================================== --- generic/tkClipboard.c +++ generic/tkClipboard.c @@ -3,12 +3,12 @@ * * This file manages the clipboard for the Tk toolkit, maintaining a * collection of data buffers that will be supplied on demand to * requesting applications. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -452,11 +452,11 @@ enum appendOptions { APPEND_DISPLAYOF, APPEND_FORMAT, APPEND_TYPE }; int subIndex; TkSizeT length; for (i = 2; i < objc - 1; i++) { - string = TkGetStringFromObj(objv[i], &length); + string = Tcl_GetStringFromObj(objv[i], &length); if (string[0] != '-') { break; } /* @@ -707,11 +707,17 @@ * selection. */ TCL_UNUSED(Tcl_Interp *), /* Interpreter used for error reporting (not * used). */ const char *portion) /* New information to be appended. */ { - Tcl_DStringAppend((Tcl_DString *)clientData, portion, -1); + Tcl_Encoding utf8 = Tcl_GetEncoding(NULL, "utf-8"); + Tcl_DString ds; + + Tcl_ExternalToUtfDString(utf8, portion, -1, &ds); + Tcl_DStringAppend((Tcl_DString *) clientData, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + Tcl_FreeEncoding(utf8); return TCL_OK; } /* * Local Variables: Index: generic/tkCmds.c ================================================================== --- generic/tkCmds.c +++ generic/tkCmds.c @@ -2,13 +2,13 @@ * tkCmds.c -- * * This file contains a collection of Tk-related Tcl commands that didn't * fit in any particular file of the toolkit. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2000 Scriptics Corporation. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1111,18 +1111,20 @@ } static char * WaitVariableProc( ClientData clientData, /* Pointer to integer to set to 1. */ - TCL_UNUSED(Tcl_Interp *), /* Interpreter containing variable. */ - TCL_UNUSED(const char *), /* Name of variable. */ + Tcl_Interp *interp, /* Interpreter containing variable. */ + const char *name1, /* Name of variable. */ TCL_UNUSED(const char *), /* Second part of variable name. */ TCL_UNUSED(int)) /* Information about what happened. */ { int *donePtr = (int *)clientData; *donePtr = 1; + Tcl_UntraceVar(interp, name1, TCL_TRACE_WRITES|TCL_TRACE_UNSETS, + WaitVariableProc, clientData); return NULL; } static void WaitVisibilityProc( @@ -1860,11 +1862,11 @@ TkSizeT length; if (objc < 1) { return 0; } - string = TkGetStringFromObj(objv[0], &length); + string = Tcl_GetStringFromObj(objv[0], &length); if ((length >= 2) && (strncmp(string, "-displayof", length) == 0)) { if (objc < 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "value for \"-displayof\" missing", -1)); Index: generic/tkColor.c ================================================================== --- generic/tkColor.c +++ generic/tkColor.c @@ -3,12 +3,12 @@ * * This file maintains a database of color values for the Tk toolkit, in * order to avoid round-trips to the server to map color names to pixel * values. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkColor.h ================================================================== --- generic/tkColor.h +++ generic/tkColor.h @@ -1,11 +1,11 @@ /* * tkColor.h -- * * Declarations of data types and functions used by the Tk color module. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkConfig.c ================================================================== --- generic/tkConfig.c +++ generic/tkConfig.c @@ -2,11 +2,11 @@ * tkConfig.c -- * * This file contains functions that manage configuration options for * widgets and other things. * - * Copyright (c) 1997-1998 Sun Microsystems, Inc. + * Copyright © 1997-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -631,10 +631,31 @@ } if (internalPtr != NULL) { *((int *) oldInternalPtr) = *((int *) internalPtr); *((int *) internalPtr) = newInt; } + break; + } + case TK_OPTION_INDEX: { + TkSizeT newIndex; + + if (TkGetIntForIndex(valuePtr, TCL_INDEX_END, 0, &newIndex) != TCL_OK) { + if (interp) { + Tcl_AppendResult(interp, "bad index \"", Tcl_GetString(valuePtr), + "\": must be integer?[+-]integer? or end?[+-]integer?", NULL); + } + return TCL_ERROR; + } + if (newIndex == TCL_INDEX_NONE) { + newIndex = (TkSizeT)INT_MIN; + } else if ((size_t)newIndex > (size_t)TCL_INDEX_END>>1) { + newIndex++; + } + if (internalPtr != NULL) { + *((int *) oldInternalPtr) = *((int *) internalPtr); + *((int *) internalPtr) = (int)newIndex; + } break; } case TK_OPTION_DOUBLE: { double newDbl; @@ -661,11 +682,11 @@ if (nullOK && ObjectIsEmpty(valuePtr)) { valuePtr = NULL; } if (internalPtr != NULL) { if (valuePtr != NULL) { - value = TkGetStringFromObj(valuePtr, &length); + value = Tcl_GetStringFromObj(valuePtr, &length); newStr = (char *)ckalloc(length + 1); strcpy(newStr, value); } else { newStr = NULL; } @@ -1404,10 +1425,11 @@ CLANG_ASSERT(internalPtr); switch (specPtr->type) { case TK_OPTION_BOOLEAN: case TK_OPTION_INT: + case TK_OPTION_INDEX: *((int *) internalPtr) = *((int *) ptr); break; case TK_OPTION_DOUBLE: *((double *) internalPtr) = *((double *) ptr); break; @@ -1876,10 +1898,25 @@ internalPtr = (char *)recordPtr + optionPtr->specPtr->internalOffset; switch (optionPtr->specPtr->type) { case TK_OPTION_BOOLEAN: case TK_OPTION_INT: objPtr = Tcl_NewWideIntObj(*((int *)internalPtr)); + break; + case TK_OPTION_INDEX: + if (*((int *) internalPtr) == INT_MIN) { + objPtr = TkNewIndexObj(TCL_INDEX_NONE); + } else if (*((int *) internalPtr) == INT_MAX) { + objPtr = Tcl_NewStringObj("end+1", -1); + } else if (*((int *) internalPtr) == -1) { + objPtr = Tcl_NewStringObj("end", -1); + } else if (*((int *) internalPtr) < 0) { + char buf[32]; + sprintf(buf, "end%d", *((int *) internalPtr)); + objPtr = Tcl_NewStringObj(buf, -1); + } else { + objPtr = Tcl_NewWideIntObj(*((int *) internalPtr)); + } break; case TK_OPTION_DOUBLE: objPtr = Tcl_NewDoubleObj(*((double *) internalPtr)); break; case TK_OPTION_STRING: Index: generic/tkConsole.c ================================================================== --- generic/tkConsole.c +++ generic/tkConsole.c @@ -3,11 +3,11 @@ * * This file implements a Tcl console for systems that may not otherwise * have access to a console. It uses the Text widget and provides special * access via a console command. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * Copyright © 1995-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkCursor.c ================================================================== --- generic/tkCursor.c +++ generic/tkCursor.c @@ -3,12 +3,12 @@ * * This file maintains a database of read-only cursors for the Tk * toolkit. This allows cursors to be shared between widgets and also * avoids round-trips to the X server. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkDList.h ================================================================== --- generic/tkDList.h +++ generic/tkDList.h @@ -5,11 +5,11 @@ * are doubly linked so that an arbitrary element can be removed without * a need to traverse the list. New elements can be added to the list * before or after an existing element or at the head/tail of the list. * A list may be traversed in the forward or backward direction. * - * Copyright (c) 2018 by Gregor Cramer. + * Copyright © 2018 Gregor Cramer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkDecls.h ================================================================== --- generic/tkDecls.h +++ generic/tkDecls.h @@ -1,11 +1,11 @@ /* * tkDecls.h -- * * Declarations of functions in the platform independent public Tcl API. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -891,10 +891,13 @@ /* 278 */ EXTERN void Tk_SendVirtualEvent(Tk_Window tkwin, const char *eventName, Tcl_Obj *detail); /* 279 */ EXTERN Tcl_Obj * Tk_FontGetDescription(Tk_Font tkfont); +/* 280 */ +EXTERN void Tk_CreatePhotoImageFormatVersion3( + const Tk_PhotoImageFormatVersion3 *formatPtr); typedef struct { const struct TkPlatStubs *tkPlatStubs; const struct TkIntStubs *tkIntStubs; const struct TkIntPlatStubs *tkIntPlatStubs; @@ -1183,10 +1186,12 @@ unsigned (*tk_GetButtonMask) (unsigned button); /* 275 */ int (*tk_GetDoublePixelsFromObj) (Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr, double *doublePtr); /* 276 */ Tcl_Obj * (*tk_NewWindowObj) (Tk_Window tkwin); /* 277 */ void (*tk_SendVirtualEvent) (Tk_Window tkwin, const char *eventName, Tcl_Obj *detail); /* 278 */ Tcl_Obj * (*tk_FontGetDescription) (Tk_Font tkfont); /* 279 */ + void (*tk_CreatePhotoImageFormatVersion3) ( + const Tk_PhotoImageFormatVersion3 *formatPtr); /* 280 */ } TkStubs; extern const TkStubs *tkStubsPtr; #ifdef __cplusplus @@ -1755,10 +1760,12 @@ (tkStubsPtr->tk_NewWindowObj) /* 277 */ #define Tk_SendVirtualEvent \ (tkStubsPtr->tk_SendVirtualEvent) /* 278 */ #define Tk_FontGetDescription \ (tkStubsPtr->tk_FontGetDescription) /* 279 */ +#define Tk_CreatePhotoImageFormatVersion3 \ + (tkStubsPtr->tk_CreatePhotoImageFormatVersion3) /* 280 */ #endif /* defined(USE_TK_STUBS) */ /* !END!: Do not edit above this line. */ @@ -1793,7 +1800,9 @@ #undef Tk_CreateOldPhotoImageFormat #endif /* TK_NO_DEPRECATED */ #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLIMPORT + +#undef TkUnusedStubEntry #endif /* _TKDECLS */ Index: generic/tkEntry.c ================================================================== --- generic/tkEntry.c +++ generic/tkEntry.c @@ -4,14 +4,14 @@ * This module implements entry and spinbox widgets for the Tk toolkit. * An entry displays a string and allows the string to be edited. A * spinbox expands on the entry by adding up/down buttons that control * the value of the entry widget. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2000 Ajuba Solutions. - * Copyright (c) 2002 ActiveState Corporation. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2000 Ajuba Solutions. + * Copyright © 2002 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -2688,11 +2688,11 @@ } *indexPtr = idx; return TCL_OK; } - string = TkGetStringFromObj(indexObj, &length); + string = Tcl_GetStringFromObj(indexObj, &length); switch (string[0]) { case 'a': if (strncmp(string, "anchor", length) != 0) { goto badIndex; @@ -4431,11 +4431,11 @@ const char *bytes; Tcl_Obj **listv; Tcl_ListObjGetElements(interp, sbPtr->listObj, &listc, &listv); for (i = 0; i < listc; i++) { - bytes = TkGetStringFromObj(listv[i], &elemLen); + bytes = Tcl_GetStringFromObj(listv[i], &elemLen); if ((length == elemLen) && (memcmp(bytes, entryPtr->string, length) == 0)) { sbPtr->eIndex = i; break; Index: generic/tkEntry.h ================================================================== --- generic/tkEntry.h +++ generic/tkEntry.h @@ -4,11 +4,11 @@ * This module defined the structures for the Entry & SpinBox widgets. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * Copyright (c) 2002 Apple Inc. + * Copyright © 2002 Apple Inc. */ #ifndef _TKENTRY #define _TKENTRY Index: generic/tkError.c ================================================================== --- generic/tkError.c +++ generic/tkError.c @@ -4,12 +4,12 @@ * This file provides a high-performance mechanism for selectively * dealing with errors that occur in talking to the X server. This is * useful, for example, when communicating with a window that may not * exist. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkEvent.c ================================================================== --- generic/tkEvent.c +++ generic/tkEvent.c @@ -2,14 +2,14 @@ * tkEvent.c -- * * This file provides basic low-level facilities for managing X events in * Tk. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 Ajuba Solutions. - * Copyright (c) 2004 George Peter Staplin + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1995 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions. + * Copyright © 2004 George Peter Staplin * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1149,11 +1149,11 @@ int but = eventPtr->xbutton.button; eventPtr->type = MouseWheelEvent; eventPtr->xany.send_event = -1; eventPtr->xkey.keycode = (but & 1) ? -120 : 120; if (but > Button5) { - eventPtr->xkey.state ^= ShiftMask; + eventPtr->xkey.state |= ShiftMask; } } } #endif Index: generic/tkFileFilter.c ================================================================== --- generic/tkFileFilter.c +++ generic/tkFileFilter.c @@ -2,11 +2,11 @@ * tkFileFilter.c -- * * Process the -filetypes option for the file dialogs on Windows and the * Mac. * - * Copyright (c) 1996 Sun Microsystems, Inc. + * Copyright © 1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -261,11 +261,11 @@ * require further code refactoring. */ for (i=0; i 0 && globList != NULL) { for (i=0; iclassProcsPtr, worldChangedProc); - + TkWindow *tkwinPtr; + if (proc != NULL) { proc(winPtr->instanceData); } /* @@ -911,22 +912,29 @@ * option will be leaf nodes in the widget heirarchy (buttons, labels, * etc.), so the recursion depth will be shallow. * * However, the additional overhead of the recursive calls may become a * performance problem if typical usage alters such that -font'ed widgets - * appear high in the heirarchy, causing deep recursion. This could happen - * with text widgets, or more likely with the (not yet existant) labeled - * frame widget. With these widgets it is possible, even likely, that a - * -font'ed widget (text or labeled frame) will not be a leaf node, but + * appear high in the hierarchy, causing deep recursion. This could happen + * with text widgets, or more likely with the labelframe + * widget. With these widgets it is possible, even likely, that a + * -font'ed widget (text or labelframe) will not be a leaf node, but * will instead have many descendants. If this is ever found to cause a * performance problem, it may be worth investigating an iterative version * of the code below. */ - for (winPtr=winPtr->childList ; winPtr!=NULL ; winPtr=winPtr->nextPtr) { - RecomputeWidgets(winPtr); + for (tkwinPtr=winPtr->childList ; tkwinPtr!=NULL ; tkwinPtr=tkwinPtr->nextPtr) { + RecomputeWidgets(tkwinPtr); } + + /* + * Broadcast font change virtually for mega-widget layout managers. + * Do this after the font change has been propagated to core widgets. + */ + Tk_SendVirtualEvent((Tk_Window)winPtr, "TkWorldChanged", + Tcl_NewStringObj("FontChanged",-1)); } /* *--------------------------------------------------------------------------- * @@ -2469,11 +2477,11 @@ Tk_TextLayout layout, /* Layout information, from a previous call to * Tk_ComputeTextLayout(). */ int x, int y, /* Upper-left hand corner of rectangle in * which to draw (pixels). */ int underline) /* Index of the single character to underline, - * or -1 for no underline. */ + * or INT_MIN for no underline. */ { int xx, yy, width, height; if ((Tk_CharBbox(layout, underline, &xx, &yy, &width, &height) != 0) && (width != 0)) { @@ -2496,11 +2504,11 @@ * Tk_ComputeTextLayout(). */ int x, int y, /* Upper-left hand corner of rectangle in * which to draw (pixels). */ double angle, int underline) /* Index of the single character to underline, - * or -1 for no underline. */ + * or INT_MIN for no underline. */ { int xx, yy, width, height; if (angle == 0.0) { Tk_UnderlineTextLayout(display, drawable, gc, layout, x,y, underline); @@ -2724,11 +2732,11 @@ int Tk_CharBbox( Tk_TextLayout layout, /* Layout information, from a previous call to * Tk_ComputeTextLayout(). */ int index, /* The index of the character whose bbox is - * desired. */ + * desired. Negative means count backwards. */ int *xPtr, int *yPtr, /* Filled with the upper-left hand corner, in * pixels, of the bounding box for the * character specified by index, if * non-NULL. */ int *widthPtr, int *heightPtr) @@ -2742,11 +2750,16 @@ Tk_Font tkfont; TkFont *fontPtr; const char *end; if (index < 0) { - return 0; + for (i = 0; i < layoutPtr->numChunks; i++) { + index += (chunkPtr + i)->numChars; + } + if (index < 0) { + return 0; + } } tkfont = layoutPtr->tkfont; fontPtr = (TkFont *) tkfont; @@ -3342,11 +3355,11 @@ goto noMapping; } sprintf(uindex, "%04X", ch); /* endianness? */ glyphname = Tcl_GetVar2(interp, "::tk::psglyphs", uindex, 0); if (glyphname) { - ps = TkGetStringFromObj(psObj, &len); + ps = Tcl_GetStringFromObj(psObj, &len); if (ps[len-1] == '(') { /* * In-place edit. Ewww! */ Index: generic/tkFont.h ================================================================== --- generic/tkFont.h +++ generic/tkFont.h @@ -3,11 +3,11 @@ * * Declarations for interfaces between the generic and platform-specific * parts of the font package. This information is not visible outside of * the font package. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkFrame.c ================================================================== --- generic/tkFrame.c +++ generic/tkFrame.c @@ -3,12 +3,12 @@ * * This module implements "frame", "labelframe" and "toplevel" widgets * for the Tk toolkit. Frames are windows with a background color and * possibly a 3-D effect, but not much else in the way of attributes. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -545,11 +545,11 @@ */ className = colormapName = screenName = visualName = useOption = NULL; colormap = None; for (i = 2; i < objc; i += 2) { - arg = TkGetStringFromObj(objv[i], &length); + arg = Tcl_GetStringFromObj(objv[i], &length); if (length < 2) { continue; } if ((arg[1] == 'c') && (length >= 3) && (strncmp(arg, "-class", length) == 0)) { @@ -818,11 +818,11 @@ * Don't allow the options -class, -colormap, -container, -screen, * -use, or -visual to be changed. */ for (i = 2; i < objc; i++) { - const char *arg = TkGetStringFromObj(objv[i], &length); + const char *arg = Tcl_GetStringFromObj(objv[i], &length); if (length < 2) { continue; } c = arg[1]; @@ -837,11 +837,11 @@ || ((c == 'u') && (framePtr->type == TYPE_TOPLEVEL) && (strncmp(arg, "-use", length) == 0)) || ((c == 'v') && (strncmp(arg, "-visual", length) == 0))) { -#ifdef SUPPORT_CONFIG_EMBEDDED +#ifdef _WIN32 if (c == 'u') { const char *string = Tcl_GetString(objv[i+1]); if (TkpUseWindow(interp, framePtr->tkwin, string) != TCL_OK) { Index: generic/tkGC.c ================================================================== --- generic/tkGC.c +++ generic/tkGC.c @@ -2,12 +2,12 @@ * tkGC.c -- * * This file maintains a database of read-only graphics contexts for the * Tk toolkit, in order to allow GC's to be shared. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkGeometry.c ================================================================== --- generic/tkGeometry.c +++ generic/tkGeometry.c @@ -2,12 +2,12 @@ * tkGeometry.c -- * * This file contains generic Tk code for geometry management (stuff * that's used by all geometry managers). * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkGet.c ================================================================== --- generic/tkGet.c +++ generic/tkGet.c @@ -4,12 +4,12 @@ * This file contains a number of "Tk_GetXXX" procedures, which parse * text strings into useful forms for Tk. This file has the simpler * functions, like Tk_GetDirection and Tk_GetUid. The more complex * functions like Tk_GetColor are in separate files. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -692,10 +692,15 @@ double *doublePtr) /* Place to store converted result. */ { char *end; double d; + if (!tkwin) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad screen")); + Tcl_SetErrorCode(interp, "TK", "VALUE", "FRACTIONAL_PIXELS", NULL); + return TCL_ERROR; + } d = strtod((char *) string, &end); if (end == string) { goto error; } while ((*end != '\0') && isspace(UCHAR(*end))) { Index: generic/tkGrab.c ================================================================== --- generic/tkGrab.c +++ generic/tkGrab.c @@ -1,12 +1,12 @@ /* * tkGrab.c -- * * This file provides functions that implement grabs for Tk. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -213,11 +213,11 @@ /* * First check for a window name or "-global" as the first argument. */ - arg = TkGetStringFromObj(objv[1], &len); + arg = Tcl_GetStringFromObj(objv[1], &len); if (arg[0] == '.') { /* [grab window] */ if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?-global? window"); return TCL_ERROR; Index: generic/tkGrid.c ================================================================== --- generic/tkGrid.c +++ generic/tkGrid.c @@ -1,11 +1,11 @@ /* * tkGrid.c -- * * Grid based geometry manager. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -2984,11 +2984,11 @@ firstChar = 0; for (numWindows=0, i=0; i < objc; i++) { TkSizeT length; char prevChar = firstChar; - string = TkGetStringFromObj(objv[i], &length); + string = Tcl_GetStringFromObj(objv[i], &length); firstChar = string[0]; if (firstChar == '.') { /* * Check that windows are valid, and locate the first content's Index: generic/tkImage.c ================================================================== --- generic/tkImage.c +++ generic/tkImage.c @@ -2,12 +2,12 @@ * tkImage.c -- * * This module implements the image protocol, which allows lots of * different kinds of images to be used in lots of different widgets. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkImgBmap.c ================================================================== --- generic/tkImgBmap.c +++ generic/tkImgBmap.c @@ -1,13 +1,13 @@ /* * tkImgBmap.c -- * * This procedure implements images of type "bitmap" for Tk. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1999 by Scriptics Corporation. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkImgGIF.c ================================================================== --- generic/tkImgGIF.c +++ generic/tkImgGIF.c @@ -6,14 +6,14 @@ * read using the -data option of the photo image. The data may be given * as a binary string in a Tcl_Obj or by representing the data as BASE64 * encoded ascii. Derived from the giftoppm code found in the pbmplus * package and tkImgFmtPPM.c in the tk4.0b2 distribution. * - * Copyright (c) Reed Wade (wade@cs.utk.edu), University of Tennessee - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 1997 Australian National University - * Copyright (c) 2005-2010 Donal K. Fellows + * Copyright © Reed Wade (wade@cs.utk.edu), University of Tennessee + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 1997 Australian National University + * Copyright © 2005-2010 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This file also contains code from the giftoppm program, which is @@ -116,32 +116,41 @@ /* * The format record for the GIF file format: */ -static int FileMatchGIF(Tcl_Channel chan, const char *fileName, - Tcl_Obj *format, int *widthPtr, int *heightPtr, - Tcl_Interp *interp); +static int FileMatchGIF(Tcl_Interp *interp, Tcl_Channel chan, + const char *fileName, Tcl_Obj *format, + Tcl_Obj *metadataInObj, int *widthPtr, + int *heightPtr, Tcl_Obj *metadataOutObj); static int FileReadGIF(Tcl_Interp *interp, Tcl_Channel chan, const char *fileName, Tcl_Obj *format, - Tk_PhotoHandle imageHandle, int destX, int destY, - int width, int height, int srcX, int srcY); -static int StringMatchGIF(Tcl_Obj *dataObj, Tcl_Obj *format, - int *widthPtr, int *heightPtr, Tcl_Interp *interp); -static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj, - Tcl_Obj *format, Tk_PhotoHandle imageHandle, - int destX, int destY, int width, int height, - int srcX, int srcY); -static int FileWriteGIF(Tcl_Interp *interp, const char *filename, - Tcl_Obj *format, Tk_PhotoImageBlock *blockPtr); -static int StringWriteGIF(Tcl_Interp *interp, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr); -static int CommonWriteGIF(Tcl_Interp *interp, ClientData clientData, - WriteBytesFunc *writeProc, Tcl_Obj *format, - Tk_PhotoImageBlock *blockPtr); - -Tk_PhotoImageFormat tkImgFmtGIF = { + Tcl_Obj *metadataInObj, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY, Tcl_Obj *metadataOutObj); +static int StringMatchGIF(Tcl_Interp *interp, Tcl_Obj *dataObj, + Tcl_Obj *format, Tcl_Obj *metadataInObj, + int *widthPtr, int *heightPtr, + Tcl_Obj *metadataOutObj); +static int StringReadGIF(Tcl_Interp *interp, Tcl_Obj *dataObj, + Tcl_Obj *format, Tcl_Obj *metadataInObj, + Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY, Tcl_Obj *metadataOutObj); +static int FileWriteGIF(Tcl_Interp *interp, const char *filename, + Tcl_Obj *format, Tcl_Obj *metadataInObj, + Tk_PhotoImageBlock *blockPtr); +static int StringWriteGIF(Tcl_Interp *interp, Tcl_Obj *format, + Tcl_Obj *metadataInObj, + Tk_PhotoImageBlock *blockPtr); +static int CommonWriteGIF(Tcl_Interp *interp, + ClientData clientData, + WriteBytesFunc *writeProc, Tcl_Obj *format, + Tcl_Obj *metadataInObj, + Tk_PhotoImageBlock *blockPtr); + +Tk_PhotoImageFormatVersion3 tkImgFmtGIF = { "gif", /* name */ FileMatchGIF, /* fileMatchProc */ StringMatchGIF, /* stringMatchProc */ FileReadGIF, /* fileReadProc */ StringReadGIF, /* stringReadProc */ @@ -163,13 +172,15 @@ /* * Prototypes for local functions defined in this file: */ +static int ReadOneByte(Tcl_Interp *interp, + GIFImageConfig *gifConfPtr, Tcl_Channel chan); static int DoExtension(GIFImageConfig *gifConfPtr, Tcl_Channel chan, int label, unsigned char *buffer, - int *transparent); + int *transparent, Tcl_Obj *metadataOutObj); static int GetCode(Tcl_Channel chan, int code_size, int flag, GIFImageConfig *gifConfPtr); static int GetDataBlock(GIFImageConfig *gifConfPtr, Tcl_Channel chan, unsigned char *buf); static int ReadColorMap(GIFImageConfig *gifConfPtr, @@ -343,22 +354,21 @@ *---------------------------------------------------------------------- */ static int FileMatchGIF( + TCL_UNUSED(Tcl_Interp *), /* not used */ Tcl_Channel chan, /* The image file, open for reading. */ - const char *fileName, /* The name of the image file. */ - Tcl_Obj *format, /* User-specified format object, or NULL. */ + TCL_UNUSED(const char *), /* The name of the image file. */ + TCL_UNUSED(Tcl_Obj *), /* User-specified format object, or NULL. */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ int *widthPtr, int *heightPtr, /* The dimensions of the image are returned * here if the file is a valid raw GIF file. */ - Tcl_Interp *dummy) /* not used */ + TCL_UNUSED(Tcl_Obj *)) /* metadata return dict, may be NULL */ { GIFImageConfig gifConf; - (void)fileName; - (void)format; - (void)dummy; memset(&gifConf, 0, sizeof(GIFImageConfig)); return ReadGIFHeader(&gifConf, chan, widthPtr, heightPtr); } @@ -385,25 +395,28 @@ FileReadGIF( Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ Tcl_Channel chan, /* The image file, open for reading. */ const char *fileName, /* The name of the image file. */ Tcl_Obj *format, /* User-specified format object, or NULL. */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ Tk_PhotoHandle imageHandle, /* The photo image to write into. */ int destX, int destY, /* Coordinates of top-left pixel in photo * image to be written to. */ int width, int height, /* Dimensions of block of photo image to be * written to. */ - int srcX, int srcY) /* Coordinates of top-left pixel to be used in + int srcX, int srcY, /* Coordinates of top-left pixel to be used in * image being read. */ + Tcl_Obj *metadataOutObj) /* metadata return dict, may be NULL */ { int fileWidth, fileHeight, imageWidth, imageHeight; unsigned int nBytes; int index = 0, argc = 0, i, result = TCL_ERROR; Tcl_Obj **objv; unsigned char buf[100]; unsigned char *trashBuffer = NULL; int bitPixel; + int gifLabel; unsigned char colorMap[MAXCOLORMAPSIZE][4]; int transparent = -1; static const char *const optionStrings[] = { "-index", NULL }; @@ -501,28 +514,26 @@ if (Tk_PhotoExpand(interp, imageHandle, destX + width, destY + height) != TCL_OK) { return TCL_ERROR; } + /* + * ------------------------------------------------------------------------- + * From here on, go to error to not leave memory leaks + * ------------------------------------------------------------------------- + */ + /* * Search for the frame from the GIF to display. */ while (1) { - if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) { - /* - * Premature end of image. - */ - - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "premature end of image data for this index", -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END", - NULL); + if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) { goto error; } - switch (buf[0]) { + switch (gifLabel) { case GIF_TERMINATOR: Tcl_SetObjResult(interp, Tcl_NewStringObj( "no image data for this index", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "NO_DATA", NULL); goto error; @@ -530,20 +541,16 @@ case GIF_EXTENSION: /* * This is a GIF extension. */ - if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) { - Tcl_SetObjResult(interp, Tcl_NewStringObj( - "error reading extension function code in GIF image", - -1)); - Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT", - NULL); + if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) { goto error; } - if (DoExtension(gifConfPtr, chan, buf[0], - gifConfPtr->workingBuffer, &transparent) < 0) { + if (DoExtension(gifConfPtr, chan, gifLabel, + gifConfPtr->workingBuffer, &transparent, metadataOutObj) + < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "error reading extension in GIF image", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT", NULL); goto error; @@ -716,15 +723,57 @@ /* * We've successfully read the GIF frame (or there was nothing to read, * which suits as well). We're done. */ + + while (1) { + if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) { + goto error; + } + switch (gifLabel) { + case GIF_TERMINATOR: + break; + + case GIF_EXTENSION: + /* + * This is a GIF extension. + */ + + if (-1 == (gifLabel = ReadOneByte( interp, gifConfPtr, chan ) ) ) { + goto error; + } + if (DoExtension(gifConfPtr, chan, gifLabel, + gifConfPtr->workingBuffer, &transparent, metadataOutObj) + < 0) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "error reading extension in GIF image", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "BAD_EXT", + NULL); + goto error; + } + continue; + case GIF_START: + /* + * There should not be a second image block - bail out without error + */ + break; + default: + /* + * Not a valid start character; ignore it. + */ + + continue; + } + break; + } Tcl_SetObjResult(interp, Tcl_NewStringObj(tkImgFmtGIF.name, -1)); result = TCL_OK; - error: +error: + /* * If a trash buffer has been allocated, free it now. */ if (trashBuffer != NULL) { @@ -731,10 +780,49 @@ ckfree(trashBuffer); } return result; } + +/* + *---------------------------------------------------------------------- + * + * Read one Byte -- + * + * Read one byte (label byte) from the image stream. + * + * Results: + * The return value is 1 if the first characters in the data are like GIF + * data, and 0 otherwise. + * + * Side effects: + * The access position in the source is incremented. + * + *---------------------------------------------------------------------- + */ + +static int +ReadOneByte( + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + GIFImageConfig *gifConfPtr, + Tcl_Channel chan /* The image file, open for reading. */ + ) +{ + unsigned char buf[2]; + if (Fread(gifConfPtr, buf, 1, 1, chan) != 1) { + /* + * Premature end of image. + */ + + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "premature end of image data", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "GIF", "PREMATURE_END", NULL); + return -1; + } + return buf[0]; +} + /* *---------------------------------------------------------------------- * * StringMatchGIF -- * @@ -748,26 +836,27 @@ * Side effects: * The size of the image is placed in widthPtr and heightPtr. * *---------------------------------------------------------------------- */ + static int StringMatchGIF( + TCL_UNUSED(Tcl_Interp *), /* not used */ Tcl_Obj *dataObj, /* the object containing the image data */ - Tcl_Obj *format, /* the image format object, or NULL */ + TCL_UNUSED(Tcl_Obj *), /* the image format object, or NULL */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ int *widthPtr, /* where to put the string width */ int *heightPtr, /* where to put the string height */ - Tcl_Interp *dummy) /* not used */ + TCL_UNUSED(Tcl_Obj *)) /* metadata return dict, may be NULL */ { unsigned char *data, header[10]; TkSizeT got, length; MFile handle; - (void)format; - (void)dummy; - data = TkGetByteArrayFromObj(dataObj, &length); + data = Tcl_GetByteArrayFromObj(dataObj, &length); /* * Header is a minimum of 10 bytes. */ @@ -823,19 +912,21 @@ static int StringReadGIF( Tcl_Interp *interp, /* interpreter for reporting errors in */ Tcl_Obj *dataObj, /* object containing the image */ Tcl_Obj *format, /* format object, or NULL */ + Tcl_Obj *metadataInObj, /* metadata input, may be NULL */ Tk_PhotoHandle imageHandle, /* the image to write this data into */ int destX, int destY, /* The rectangular region of the */ int width, int height, /* image to copy */ - int srcX, int srcY) + int srcX, int srcY, + Tcl_Obj *metadataOutObj) /* metadata return dict, may be NULL */ { MFile handle, *hdlPtr = &handle; TkSizeT length; const char *xferFormat; - unsigned char *data = TkGetByteArrayFromObj(dataObj, &length); + unsigned char *data = Tcl_GetByteArrayFromObj(dataObj, &length); mInit(data, hdlPtr, length); /* * Check whether the data is Base64 encoded by doing a character-by- @@ -855,11 +946,12 @@ * Fall through to the file reader now that we have a correctly-configured * pseudo-channel to pull the data from. */ return FileReadGIF(interp, (Tcl_Channel) hdlPtr, xferFormat, format, - imageHandle, destX, destY, width, height, srcX, srcY); + metadataInObj, imageHandle, destX, destY, width, height, srcX, srcY, + metadataOutObj); } /* *---------------------------------------------------------------------- * @@ -934,52 +1026,107 @@ } } return 1; } +/* +*---------------------------------------------------------------------- +* +* DoExtension -- +* +* Process a GIF extension block +* +* Results: +* -1 to trigger an extension read error +* >= 0 ok +* +* Side effects: +* The transparent color is set if present in current extensions +* The data of the following extensions are saved to the metadata dict: +* - Application extension +* - Comment extension in key "comment" +* Plain text extensions are currently ignored. +* +*---------------------------------------------------------------------- +*/ + static int DoExtension( GIFImageConfig *gifConfPtr, Tcl_Channel chan, int label, - unsigned char *buf, - int *transparent) + unsigned char *buf, /* defined as 280 byte working buffer */ + int *transparent, + Tcl_Obj *metadataOutObj) { int count; + /* Prepare extension name + * Maximum string size: "comment" + Code(3) + trailing zero + */ + char extensionStreamName[8]; + extensionStreamName[0] = '\0'; switch (label) { case 0x01: /* Plain Text Extension */ - break; - - case 0xff: /* Application Extension */ - break; - - case 0xfe: /* Comment Extension */ - do { - count = GetDataBlock(gifConfPtr, chan, buf); - } while (count > 0); - return count; - + /* this extension is ignored, skip below */ + break; case 0xf9: /* Graphic Control Extension */ count = GetDataBlock(gifConfPtr, chan, buf); if (count < 0) { - return 1; + return -1; } if ((buf[0] & 0x1) != 0) { *transparent = buf[3]; } - - do { + break; + case 0xfe: /* Comment Extension */ + strcpy(extensionStreamName,"comment"); + /* copy the extension data below */ + break; + } + /* Add extension to dict */ + if (NULL != metadataOutObj + && extensionStreamName[0] != '\0' ) { + Tcl_Obj *ValueObj = NULL; + int length = 0; + for (;;) { count = GetDataBlock(gifConfPtr, chan, buf); - } while (count > 0); - return count; + switch (count) { + case -1: /* error */ + return -1; + case 0: /* end of data */ + if (length > 0) { + if ( TCL_OK != Tcl_DictObjPut(NULL, metadataOutObj, + Tcl_NewByteArrayObj( + (unsigned char *)extensionStreamName, + strlen(extensionStreamName)), ValueObj)) { + return -1; + } + } + /* return success */ + return 0; + default: /* block received */ + if (length == 0) { + /* first block */ + ValueObj = Tcl_NewByteArrayObj(buf, count); + length = count; + } else { + /* consecutive block */ + unsigned char *bytePtr; + bytePtr = Tcl_SetByteArrayLength(ValueObj, length+count); + memcpy(bytePtr+length,buf,count); + length += count; + } + break; + } + } /* for */ } - + /* skip eventual remaining data block bytes */ do { count = GetDataBlock(gifConfPtr, chan, buf); } while (count > 0); - return count; + return count; /* this may be -1 for error or 0 */ } static int GetDataBlock( GIFImageConfig *gifConfPtr, @@ -1032,11 +1179,12 @@ Tcl_Interp *interp, unsigned char *imagePtr, Tcl_Channel chan, int len, int rows, unsigned char cmap[MAXCOLORMAPSIZE][4], - int srcX, int srcY, + TCL_UNUSED(int), + TCL_UNUSED(int), int interlace, int transparent) { unsigned char initialCodeSize; int xpos = 0, ypos = 0, pass = 0, i, count; @@ -1047,12 +1195,10 @@ unsigned char append[(1 << MAX_LWZ_BITS)]; unsigned char stack[(1 << MAX_LWZ_BITS)*2]; unsigned char *top; int codeSize, clearCode, inCode, endCode, oldCode, maxCode; int code, firstCode, v; - (void)srcX; - (void)srcY; /* * Initialize the decoder */ @@ -1635,10 +1781,11 @@ static int FileWriteGIF( Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ const char *filename, Tcl_Obj *format, + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr) { Tcl_Channel chan = NULL; int result; @@ -1650,11 +1797,12 @@ "binary") != TCL_OK) { Tcl_Close(NULL, chan); return TCL_ERROR; } - result = CommonWriteGIF(interp, chan, WriteToChannel, format, blockPtr); + result = CommonWriteGIF(interp, chan, WriteToChannel, format, metadataInObj, + blockPtr); if (Tcl_Close(interp, chan) == TCL_ERROR) { return TCL_ERROR; } return result; @@ -1663,18 +1811,19 @@ static int StringWriteGIF( Tcl_Interp *interp, /* Interpreter to use for reporting errors and * returning the GIF data. */ Tcl_Obj *format, + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr) { int result; Tcl_Obj *objPtr = Tcl_NewObj(); Tcl_IncrRefCount(objPtr); result = CommonWriteGIF(interp, objPtr, WriteToByteArray, format, - blockPtr); + metadataInObj, blockPtr); if (result == TCL_OK) { Tcl_SetObjResult(interp, objPtr); } Tcl_DecrRefCount(objPtr); return result; @@ -1709,19 +1858,19 @@ static int CommonWriteGIF( Tcl_Interp *interp, ClientData handle, WriteBytesFunc *writeProc, - Tcl_Obj *format, + TCL_UNUSED(Tcl_Obj *), + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr) { GifWriterState state; int resolution; long width, height, x; unsigned char c; unsigned int top, left; - (void)format; top = 0; left = 0; memset(&state, 0, sizeof(state)); @@ -1840,10 +1989,54 @@ state.csize = blockPtr->height; Compress(resolution+1, handle, writeProc, ReadValue, &state); c = 0; writeProc(handle, (char *) &c, 1); + /* + * Check for metadata keys to add to file + */ + if (NULL != metadataInObj) { + Tcl_Obj *itemData; + + /* + * Check and code comment block + */ + + if (TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj, + Tcl_NewStringObj("comment",-1), + &itemData)) { + return TCL_ERROR; + } + if (itemData != NULL) { + int length; + unsigned char *comment; + comment = Tcl_GetByteArrayFromObj(itemData, &length); + if (length > 0) { + /* write comment header */ + writeProc(handle, (char *) "\x21\xfe", 2); + /* write comment blocks */ + for (;length > 0;) { + int blockLength; + unsigned char blockLengthChar; + if (length > 255) { + length -=255; + blockLength = 255; + } else { + blockLength = length; + length = 0; + } + blockLengthChar = (unsigned char) blockLength; + writeProc(handle, (char *) &blockLengthChar, 1); + writeProc(handle, (char *) comment, blockLength); + comment += blockLength; + } + /* Block terminator */ + c = 0; + writeProc(handle, (char *) &c, 1); + } + } + } c = GIF_TERMINATOR; writeProc(handle, (char *) &c, 1); return TCL_OK; } Index: generic/tkImgListFormat.c ================================================================== --- generic/tkImgListFormat.c +++ generic/tkImgListFormat.c @@ -10,14 +10,14 @@ * * This image format cannot read/write files, it is meant for string * data only. * * - * Copyright (c) 1994 The Australian National University. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002-2003 Donal K. Fellows - * Copyright (c) 2003 ActiveState Corporation. + * Copyright © 1994 The Australian National University. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2002-2003 Donal K. Fellows + * Copyright © 2003 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Authors: @@ -42,11 +42,11 @@ /* * Color name length limit: do not attempt to parse as color strings that are * longer than this limit */ -#define TK_PHOTO_MAX_COLOR_CHARS 99 +#define TK_PHOTO_MAX_COLOR_LENGTH 99 /* * Symbols for the different formats of a color string. */ @@ -411,11 +411,12 @@ * pixel for validity. */ if (Tcl_ListObjIndex(interp, rowListPtr[0], 0, &pixelData) != TCL_OK) { return 0; } - if (Tcl_GetCharLength(pixelData) > TK_PHOTO_MAX_COLOR_CHARS) { + (void)Tcl_GetString(pixelData); + if (pixelData->length > TK_PHOTO_MAX_COLOR_LENGTH) { return 0; } if (ParseColor(interp, pixelData, Tk_Display(Tk_MainWindow(interp)), Tk_Colormap(Tk_MainWindow(interp)), &dummy, &dummy, &dummy, &dummy) != TCL_OK) { @@ -773,34 +774,34 @@ unsigned char *greenPtr, unsigned char *bluePtr, unsigned char *alphaPtr) { const char *specString; - TkSizeT charCount; + TkSizeT length; /* * Find out which color format we have */ - specString = TkGetStringFromObj(specObj, &charCount); + specString = Tcl_GetStringFromObj(specObj, &length); - if (charCount == 0) { + if (length == 0) { /* Empty string */ *redPtr = *greenPtr = *bluePtr = *alphaPtr = 0; return TCL_OK; } - if (charCount > TK_PHOTO_MAX_COLOR_CHARS) { + if (length > TK_PHOTO_MAX_COLOR_LENGTH) { Tcl_SetObjResult(interp, Tcl_ObjPrintf("invalid color")); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "INVALID_COLOR", NULL); return TCL_ERROR; } if (specString[0] == '#') { - return ParseColorAsHex(interp, specString, charCount, display, + return ParseColorAsHex(interp, specString, length, display, colormap, redPtr, greenPtr, bluePtr, alphaPtr); } - if (ParseColorAsList(interp, specString, charCount, + if (ParseColorAsList(interp, specString, length, redPtr, greenPtr, bluePtr, alphaPtr) == TCL_OK) { return TCL_OK; } /* @@ -807,11 +808,11 @@ * Parsing the color as standard Tk color always is the last option tried * because TkParseColor() is very slow with values it cannot parse. */ Tcl_ResetResult(interp); - return ParseColorAsStandard(interp, specString, charCount, display, + return ParseColorAsStandard(interp, specString, length, display, colormap, redPtr, greenPtr, bluePtr, alphaPtr); } /* @@ -1003,11 +1004,11 @@ unsigned char *bluePtr, unsigned char *alphaPtr) { XColor parsedColor; const char *suffixString, *colorString; - char colorBuffer[TK_PHOTO_MAX_COLOR_CHARS + 1]; + char colorBuffer[TK_PHOTO_MAX_COLOR_LENGTH + 1]; char *tmpString; double fracAlpha; unsigned int suffixAlpha; int i; Index: generic/tkImgPNG.c ================================================================== --- generic/tkImgPNG.c +++ generic/tkImgPNG.c @@ -1,12 +1,12 @@ /* * tkImgPNG.c -- * * A Tk photo image file handler for PNG files. * - * Copyright (c) 2006-2008 Muonics, Inc. - * Copyright (c) 2008 Donal K. Fellows + * Copyright © 2006-2008 Muonics, Inc. + * Copyright © 2008 Donal K. Fellows * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -173,10 +173,19 @@ * not bound to a Tcl command. */ Tcl_Obj *lastLineObj; /* Last line of pixels, for unfiltering. */ Tcl_Obj *thisLineObj; /* Current line of pixels to process. */ int lineSize; /* Number of bytes in a PNG line. */ int phaseSize; /* Number of bytes/line in current phase. */ + + + /* + * Physical size: pHYS chunks. + */ + + double DPI; + double aspect; + } PNGImage; /* * Maximum size of various chunks. */ @@ -196,20 +205,24 @@ static int DecodeLine(Tcl_Interp *interp, PNGImage *pngPtr); static int DecodePNG(Tcl_Interp *interp, PNGImage *pngPtr, Tcl_Obj *fmtObj, Tk_PhotoHandle imageHandle, int destX, int destY); static int EncodePNG(Tcl_Interp *interp, - Tk_PhotoImageBlock *blockPtr, PNGImage *pngPtr); -static int FileMatchPNG(Tcl_Channel chan, const char *fileName, - Tcl_Obj *fmtObj, int *widthPtr, int *heightPtr, - Tcl_Interp *interp); + Tk_PhotoImageBlock *blockPtr, PNGImage *pngPtr, + Tcl_Obj *metadataInObj); +static int FileMatchPNG(Tcl_Interp *interp, Tcl_Channel chan, + const char *fileName, Tcl_Obj *fmtObj, + Tcl_Obj *metadataInObj, int *widthPtr, + int *heightPtr, Tcl_Obj *metadataOut); static int FileReadPNG(Tcl_Interp *interp, Tcl_Channel chan, const char *fileName, Tcl_Obj *fmtObj, - Tk_PhotoHandle imageHandle, int destX, int destY, - int width, int height, int srcX, int srcY); + Tcl_Obj *metadataInObj, Tk_PhotoHandle imageHandle, + int destX, int destY, int width, int height, + int srcX, int srcY, Tcl_Obj *metadataOutPtr); static int FileWritePNG(Tcl_Interp *interp, const char *filename, - Tcl_Obj *fmtObj, Tk_PhotoImageBlock *blockPtr); + Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj, + Tk_PhotoImageBlock *blockPtr); static int InitPNGImage(Tcl_Interp *interp, PNGImage *pngPtr, Tcl_Channel chan, Tcl_Obj *objPtr, int dir); static inline unsigned char Paeth(int a, int b, int c); static int ParseFormat(Tcl_Interp *interp, Tcl_Obj *fmtObj, PNGImage *pngPtr); @@ -234,18 +247,22 @@ int chunkSz, unsigned long crc); static int ReadTRNS(Tcl_Interp *interp, PNGImage *pngPtr, int chunkSz, unsigned long crc); static int SkipChunk(Tcl_Interp *interp, PNGImage *pngPtr, int chunkSz, unsigned long crc); -static int StringMatchPNG(Tcl_Obj *dataObj, Tcl_Obj *fmtObj, +static int StringMatchPNG(Tcl_Interp *interp, Tcl_Obj *pObjData, + Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj, int *widthPtr, int *heightPtr, - Tcl_Interp *interp); -static int StringReadPNG(Tcl_Interp *interp, Tcl_Obj *dataObj, - Tcl_Obj *fmtObj, Tk_PhotoHandle imageHandle, + Tcl_Obj *metadataOutObj); +static int StringReadPNG(Tcl_Interp *interp, Tcl_Obj *pObjData, + Tcl_Obj *fmtObj, Tcl_Obj *metadataInObj, + Tk_PhotoHandle imageHandle, int destX, int destY, int width, int height, - int srcX, int srcY); + int srcX, int srcY, Tcl_Obj *metadataOutObj); + static int StringWritePNG(Tcl_Interp *interp, Tcl_Obj *fmtObj, + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr); static int UnfilterLine(Tcl_Interp *interp, PNGImage *pngPtr); static inline int WriteByte(Tcl_Interp *interp, PNGImage *pngPtr, unsigned char c, unsigned long *crcPtr); static inline int WriteChunk(Tcl_Interp *interp, PNGImage *pngPtr, @@ -253,11 +270,11 @@ const unsigned char *dataPtr, size_t dataSize); static int WriteData(Tcl_Interp *interp, PNGImage *pngPtr, const unsigned char *srcPtr, size_t srcSz, unsigned long *crcPtr); static int WriteExtraChunks(Tcl_Interp *interp, - PNGImage *pngPtr); + PNGImage *pngPtr, Tcl_Obj *metadataInObj); static int WriteIHDR(Tcl_Interp *interp, PNGImage *pngPtr, Tk_PhotoImageBlock *blockPtr); static int WriteIDAT(Tcl_Interp *interp, PNGImage *pngPtr, Tk_PhotoImageBlock *blockPtr); static inline int WriteInt32(Tcl_Interp *interp, PNGImage *pngPtr, @@ -265,11 +282,11 @@ /* * The format record for the PNG file format: */ -Tk_PhotoImageFormat tkImgFmtPNG = { +Tk_PhotoImageFormatVersion3 tkImgFmtPNG = { "png", /* name */ FileMatchPNG, /* fileMatchProc */ StringMatchPNG, /* stringMatchProc */ FileReadPNG, /* fileReadProc */ StringReadPNG, /* stringReadProc */ @@ -317,11 +334,11 @@ if (objPtr) { Tcl_IncrRefCount(objPtr); pngPtr->objDataPtr = objPtr; pngPtr->strDataBuf = - TkGetByteArrayFromObj(objPtr, &pngPtr->strDataLen); + Tcl_GetByteArrayFromObj(objPtr, &pngPtr->strDataLen); } /* * Initialize the palette transparency table to fully opaque. */ @@ -343,10 +360,17 @@ Tcl_DecrRefCount(objPtr); } return TCL_ERROR; } + /* + * Initialize physical size pHYS values + */ + + pngPtr->DPI = -1; + pngPtr->aspect = -1; + return TCL_OK; } /* *---------------------------------------------------------------------- @@ -931,10 +955,11 @@ */ case CHUNK_IDAT: case CHUNK_IEND: case CHUNK_IHDR: + case CHUNK_pHYs: case CHUNK_PLTE: case CHUNK_tRNS: break; /* @@ -949,11 +974,10 @@ case CHUNK_hIST: case CHUNK_iCCP: case CHUNK_iTXt: case CHUNK_oFFs: case CHUNK_pCAL: - case CHUNK_pHYs: case CHUNK_sBIT: case CHUNK_sCAL: case CHUNK_sPLT: case CHUNK_sRGB: case CHUNK_tEXt: @@ -1261,11 +1285,11 @@ /* * If reading from string, reset position and try base64 decode. */ if (mismatch && pngPtr->strDataBuf) { - pngPtr->strDataBuf = TkGetByteArrayFromObj(pngPtr->objDataPtr, + pngPtr->strDataBuf = Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, &pngPtr->strDataLen); pngPtr->base64Data = pngPtr->strDataBuf; if (ReadData(interp, pngPtr, sigBuf, PNG_SIG_SZ, NULL) == TCL_ERROR) { return TCL_ERROR; @@ -1641,10 +1665,88 @@ } /* *---------------------------------------------------------------------- * + * ReadPHYS -- + * + * This function reads the PHYS (physical size) chunk data from + * the PNG file and populates the fields in the PNGImage + * structure. + * + * Results: + * TCL_OK, or TCL_ERROR if an I/O error occurs or the PHYS chunk is + * invalid. + * + * Side effects: + * The access position in f advances. + * + *---------------------------------------------------------------------- + */ + +static int +ReadPHYS( + Tcl_Interp *interp, + PNGImage *pngPtr, + int chunkSz, + unsigned long crc) +{ + unsigned long PPUx, PPUy; + char unitSpecifier; + + /* + * Check chunk size equal 9 bytes + */ + + if (chunkSz != 9) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "invalid physical chunk size", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_PHYS", NULL); + return TCL_ERROR; + } + + /* + * Read the chunk data + * 4 bytes: Pixels per unit, x axis + * 4 bytes: Pixels per unit, y axis + * 1 byte: unit specifier + */ + + if (ReadInt32(interp, pngPtr, &PPUx, &crc) == TCL_ERROR) { + return TCL_ERROR; + } + if (ReadInt32(interp, pngPtr, &PPUy, &crc) == TCL_ERROR) { + return TCL_ERROR; + } + if (ReadData(interp, pngPtr, (unsigned char *)&unitSpecifier, 1, &crc) == TCL_ERROR) { + return TCL_ERROR; + } + + if (CheckCRC(interp, pngPtr, crc) == TCL_ERROR) { + return TCL_ERROR; + } + + if ( PPUx > 2147483647 || PPUy > 2147483647 + || unitSpecifier > 1 ) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "invalid physical size value", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "BAD_PHYS", NULL); + return TCL_ERROR; + } + + if (PPUx > 0) { + pngPtr->aspect = ((double) PPUy) / ((double) PPUx); + } + if (1 == unitSpecifier) { + pngPtr->DPI = ((double) PPUx) * 0.0254; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * * Paeth -- * * Utility function for applying the Paeth filter to a pixel. The Paeth * filter is a linear function of the pixel to be filtered and the pixels * to the left, above, and above-left of the pixel to be unfiltered. @@ -1706,13 +1808,13 @@ UnfilterLine( Tcl_Interp *interp, PNGImage *pngPtr) { unsigned char *thisLine = - Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, NULL); + Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, (int *)NULL); unsigned char *lastLine = - Tcl_GetByteArrayFromObj(pngPtr->lastLineObj, NULL); + Tcl_GetByteArrayFromObj(pngPtr->lastLineObj, (int *)NULL); #define PNG_FILTER_NONE 0 #define PNG_FILTER_SUB 1 #define PNG_FILTER_UP 2 #define PNG_FILTER_AVG 3 @@ -1838,11 +1940,11 @@ int shifts = 0; /* Number of channels extracted from byte */ int offset = 0; /* Current offset into pixelPtr */ int colStep = 1; /* Column increment each pass */ int pixStep = 0; /* extra pixelPtr increment each pass */ unsigned char lastPixel[6]; - unsigned char *p = Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, NULL); + unsigned char *p = Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, (int *)NULL); p++; if (UnfilterLine(interp, pngPtr) == TCL_ERROR) { return TCL_ERROR; } @@ -2144,16 +2246,16 @@ * Inflate, processing each output buffer's worth as a line of pixels, * until we cannot fill the buffer any more. */ getNextLine: - TkGetByteArrayFromObj(pngPtr->thisLineObj, &len1); + Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len1); if (Tcl_ZlibStreamGet(pngPtr->stream, pngPtr->thisLineObj, pngPtr->phaseSize - len1) == TCL_ERROR) { return TCL_ERROR; } - TkGetByteArrayFromObj(pngPtr->thisLineObj, &len2); + Tcl_GetByteArrayFromObj(pngPtr->thisLineObj, &len2); if (len2 == (TkSizeT)pngPtr->phaseSize) { if (pngPtr->phase > 7) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "extra data after final scan line of final phase", @@ -2412,10 +2514,33 @@ if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType, &crc) == TCL_ERROR) { return TCL_ERROR; } + + /* + * Physical header may be present here so try to parse it + */ + + if (CHUNK_pHYs == chunkType) { + /* + * Finish parsing the PHYS chunk. + */ + + if (ReadPHYS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) { + return TCL_ERROR; + } + + /* + * Begin the next chunk. + */ + + if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType, + &crc) == TCL_ERROR) { + return TCL_ERROR; + } + } if (CHUNK_PLTE == chunkType) { /* * Finish parsing the PLTE chunk. */ @@ -2452,10 +2577,33 @@ */ if (ReadTRNS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) { return TCL_ERROR; } + + /* + * Begin the next chunk. + */ + + if (ReadChunkHeader(interp, pngPtr, &chunkSz, &chunkType, + &crc) == TCL_ERROR) { + return TCL_ERROR; + } + } + + /* + * Physical header may be present here so try to parse it + */ + + if (CHUNK_pHYs == chunkType) { + /* + * Finish parsing the PHYS chunk. + */ + + if (ReadPHYS(interp, pngPtr, chunkSz, crc) == TCL_ERROR) { + return TCL_ERROR; + } /* * Begin the next chunk. */ @@ -2665,21 +2813,22 @@ *---------------------------------------------------------------------- */ static int FileMatchPNG( - Tcl_Channel chan, - const char *fileName, - Tcl_Obj *fmtObj, - int *widthPtr, - int *heightPtr, - Tcl_Interp *interp) + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + TCL_UNUSED(const char *), /* The name of the image file. */ + TCL_UNUSED(Tcl_Obj *), /* User-specified format object, or NULL. */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ + int *widthPtr, int *heightPtr, + /* The dimensions of the image are returned + * here if the file is a valid raw GIF file. */ + TCL_UNUSED(Tcl_Obj *)) /* metadata return dict, may be NULL */ { PNGImage png; int match = 0; - (void)fileName; - (void)fmtObj; InitPNGImage(NULL, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE); if (ReadIHDR(interp, &png) == TCL_OK) { *widthPtr = png.block.width; @@ -2711,35 +2860,46 @@ *---------------------------------------------------------------------- */ static int FileReadPNG( - Tcl_Interp *interp, - Tcl_Channel chan, - const char *fileName, - Tcl_Obj *fmtObj, - Tk_PhotoHandle imageHandle, - int destX, - int destY, - int width, - int height, - int srcX, - int srcY) + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Channel chan, /* The image file, open for reading. */ + TCL_UNUSED(const char *), /* The name of the image file. */ + Tcl_Obj *fmtObj, /* User-specified format object, or NULL. */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ + Tk_PhotoHandle imageHandle, /* The photo image to write into. */ + int destX, int destY, /* Coordinates of top-left pixel in photo + * image to be written to. */ + TCL_UNUSED(int), /* Dimensions of block of photo image to be + * written to. */ + TCL_UNUSED(int), + TCL_UNUSED(int), /* Coordinates of top-left pixel to be used in + * image being read. */ + TCL_UNUSED(int), + Tcl_Obj *metadataOutObj) /* metadata return dict, may be NULL */ { PNGImage png; int result = TCL_ERROR; - (void)fileName; - (void)width; - (void)height; - (void)srcX; - (void)srcY; result = InitPNGImage(interp, &png, chan, NULL, TCL_ZLIB_STREAM_INFLATE); if (TCL_OK == result) { result = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY); } + + if (TCL_OK == result && metadataOutObj != NULL && png.DPI != -1) { + result = Tcl_DictObjPut(NULL, metadataOutObj, + Tcl_NewStringObj("DPI",-1), + Tcl_NewDoubleObj(png.DPI)); + } + + if (TCL_OK == result && metadataOutObj != NULL && png.aspect != -1) { + result = Tcl_DictObjPut(NULL, metadataOutObj, + Tcl_NewStringObj("aspect",-1), + Tcl_NewDoubleObj(png.aspect)); + } CleanupPNGImage(&png); return result; } @@ -2761,23 +2921,24 @@ *---------------------------------------------------------------------- */ static int StringMatchPNG( - Tcl_Obj *pObjData, - Tcl_Obj *fmtObj, - int *widthPtr, - int *heightPtr, - Tcl_Interp *interp) + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tcl_Obj *pObjData, /* the object containing the image data */ + TCL_UNUSED(Tcl_Obj *), /* the image format object, or NULL */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ + int *widthPtr, /* where to put the string width */ + int *heightPtr, /* where to put the string height */ + TCL_UNUSED(Tcl_Obj *)) /* metadata return dict, may be NULL */ { PNGImage png; int match = 0; - (void)fmtObj; InitPNGImage(NULL, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE); - png.strDataBuf = TkGetByteArrayFromObj(pObjData, &png.strDataLen); + png.strDataBuf = Tcl_GetByteArrayFromObj(pObjData, &png.strDataLen); if (ReadIHDR(interp, &png) == TCL_OK) { *widthPtr = png.block.width; *heightPtr = png.block.height; match = 1; @@ -2805,34 +2966,43 @@ *---------------------------------------------------------------------- */ static int StringReadPNG( - Tcl_Interp *interp, - Tcl_Obj *pObjData, - Tcl_Obj *fmtObj, - Tk_PhotoHandle imageHandle, - int destX, - int destY, - int width, - int height, - int srcX, - int srcY) + Tcl_Interp *interp, /* interpreter for reporting errors in */ + Tcl_Obj *pObjData, /* object containing the image */ + Tcl_Obj *fmtObj, /* format object, or NULL */ + TCL_UNUSED(Tcl_Obj *), /* metadata input, may be NULL */ + Tk_PhotoHandle imageHandle, /* the image to write this data into */ + int destX, int destY, /* The rectangular region of the */ + TCL_UNUSED(int), /* image to copy */ + TCL_UNUSED(int), + TCL_UNUSED(int), + TCL_UNUSED(int), + Tcl_Obj *metadataOutObj) /* metadata return dict, may be NULL */ { PNGImage png; int result = TCL_ERROR; - (void)width; - (void)height; - (void)srcX; - (void)srcY; result = InitPNGImage(interp, &png, NULL, pObjData, TCL_ZLIB_STREAM_INFLATE); if (TCL_OK == result) { result = DecodePNG(interp, &png, fmtObj, imageHandle, destX, destY); } + + if (TCL_OK == result && metadataOutObj != NULL && png.DPI != -1) { + result = Tcl_DictObjPut(NULL, metadataOutObj, + Tcl_NewStringObj("DPI",-1), + Tcl_NewDoubleObj(png.DPI)); + } + + if (TCL_OK == result && metadataOutObj != NULL && png.aspect != -1) { + result = Tcl_DictObjPut(NULL, metadataOutObj, + Tcl_NewStringObj("aspect",-1), + Tcl_NewDoubleObj(png.aspect)); + } CleanupPNGImage(&png); return result; } @@ -2875,11 +3045,11 @@ if (pngPtr->objDataPtr) { TkSizeT objSz; unsigned char *destPtr; - TkGetByteArrayFromObj(pngPtr->objDataPtr, &objSz); + Tcl_GetByteArrayFromObj(pngPtr->objDataPtr, &objSz); if (objSz + srcSz > INT_MAX) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "image too large to store completely in byte array", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "TOO_LARGE", NULL); @@ -2916,10 +3086,38 @@ } /* *---------------------------------------------------------------------- * + * LongToInt32 -- + * + * This function transforms to a 32-bit integer value as + * four bytes in network byte order. + * + * Results: + * None + * + * Side effects: + * Buffer will be modified. + * + *---------------------------------------------------------------------- + */ + +static inline void +LongToInt32( + unsigned long l, + unsigned char *pc) +{ + pc[0] = (unsigned char) ((l & 0xff000000) >> 24); + pc[1] = (unsigned char) ((l & 0x00ff0000) >> 16); + pc[2] = (unsigned char) ((l & 0x0000ff00) >> 8); + pc[3] = (unsigned char) ((l & 0x000000ff) >> 0); +} + +/* + *---------------------------------------------------------------------- + * * WriteInt32 -- * * This function writes a 32-bit integer value out to the PNG image as * four bytes in network byte order. * @@ -2938,16 +3136,11 @@ PNGImage *pngPtr, unsigned long l, unsigned long *crcPtr) { unsigned char pc[4]; - - pc[0] = (unsigned char) ((l & 0xff000000) >> 24); - pc[1] = (unsigned char) ((l & 0x00ff0000) >> 16); - pc[2] = (unsigned char) ((l & 0x0000ff00) >> 8); - pc[3] = (unsigned char) ((l & 0x000000ff) >> 0); - + LongToInt32(l,pc); return WriteData(interp, pngPtr, pc, 4, crcPtr); } /* *---------------------------------------------------------------------- @@ -3236,11 +3429,11 @@ * Now get the compressed data and write it as one big IDAT chunk. */ outputObj = Tcl_NewObj(); (void) Tcl_ZlibStreamGet(pngPtr->stream, outputObj, -1); - outputBytes = TkGetByteArrayFromObj(outputObj, &outputSize); + outputBytes = Tcl_GetByteArrayFromObj(outputObj, &outputSize); result = WriteChunk(interp, pngPtr, CHUNK_IDAT, outputBytes, outputSize); Tcl_DecrRefCount(outputObj); return result; } @@ -3262,11 +3455,12 @@ */ static int WriteExtraChunks( Tcl_Interp *interp, - PNGImage *pngPtr) + PNGImage *pngPtr, + Tcl_Obj *metadataInObj) { static const unsigned char sBIT_contents[] = { 8, 8, 8, 8 }; int sBIT_length = 4; @@ -3314,10 +3508,83 @@ Tcl_DStringFree(&buf); return TCL_ERROR; } Tcl_DStringFree(&buf); + /* + * Add a pHYs chunk if there is metadata for DPI and/or aspect + * aspect = PPUy / PPUx + * DPI = PPUx * 0.0254 + * The physical chunk consists of: + * - Points per meter in x direction (32 bit) + * - Points per meter in x direction (32 bit) + * - Unit specifier: 0: no unit (only aspect), 1: Points per meter + */ + + if (metadataInObj != NULL) { + + Tcl_Obj *aspectObj, *DPIObj; + double aspectValue=-1, DPIValue=-1; + unsigned long PPUx = 65536, PPUy = 65536; + char unitSpecifier; + + if (TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj, + Tcl_NewStringObj("aspect",-1), + &aspectObj) || + TCL_ERROR == Tcl_DictObjGet(interp, metadataInObj, + Tcl_NewStringObj("DPI",-1), + &DPIObj) ) { + return TCL_ERROR; + } + if (DPIObj != NULL) { + if (TCL_ERROR == Tcl_GetDoubleFromObj(interp, DPIObj, &DPIValue)) + { + return TCL_ERROR; + } + PPUx = (unsigned long)floor(DPIValue / 0.0254+0.5); + if (aspectObj == NULL) { + PPUy = PPUx; + } + unitSpecifier = 1; + } + if (aspectObj != NULL) { + if (TCL_ERROR == Tcl_GetDoubleFromObj(interp, aspectObj, + &aspectValue)) { + return TCL_ERROR; + } + + /* + * aspect = PPUy / PPUx + */ + + if (DPIObj == NULL) { + unitSpecifier = 0; + PPUx = 65536; + PPUy = (unsigned long)floor(65536.0 * aspectValue+0.5); + } else { + PPUy = (unsigned long)floor(DPIValue * aspectValue / 0.0254+0.5); + } + } + if (DPIObj != NULL || aspectObj != NULL) { + unsigned char buffer[9]; + + if ( PPUx > 2147483647 || PPUy > 2147483647 ) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "DPI or aspect out of range", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PNG", "PHYS", NULL); + return TCL_ERROR; + } + + LongToInt32(PPUx, buffer); + LongToInt32(PPUy, buffer+4); + buffer[8] = unitSpecifier; + if (WriteChunk(interp, pngPtr, CHUNK_pHYs, buffer, 9) + != TCL_OK) { + return TCL_ERROR; + } + } + } return TCL_OK; } /* *---------------------------------------------------------------------- @@ -3339,11 +3606,12 @@ static int EncodePNG( Tcl_Interp *interp, Tk_PhotoImageBlock *blockPtr, - PNGImage *pngPtr) + PNGImage *pngPtr, + Tcl_Obj *metadataInObj) { int greenOffset, blueOffset, alphaOffset; /* * Determine appropriate color type based on color usage (e.g., only red @@ -3422,11 +3690,11 @@ /* * Write out the extra chunks containing metadata that is of interest to * other programs more than us. */ - if (WriteExtraChunks(interp, pngPtr) == TCL_ERROR) { + if (WriteExtraChunks(interp, pngPtr, metadataInObj) == TCL_ERROR) { return TCL_ERROR; } /* * Write out the image pixels in the IDAT (data) chunk. @@ -3463,17 +3731,17 @@ static int FileWritePNG( Tcl_Interp *interp, const char *filename, - Tcl_Obj *fmtObj, + TCL_UNUSED(Tcl_Obj *), + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr) { Tcl_Channel chan; PNGImage png; int result = TCL_ERROR; - (void)fmtObj; /* * Open a Tcl file channel where the image data will be stored. Tk ought * to take care of this, and just provide a channel, but it doesn't. */ @@ -3505,11 +3773,11 @@ /* * Write the raw PNG data out to the file. */ - result = EncodePNG(interp, blockPtr, &png); + result = EncodePNG(interp, blockPtr, &png, metadataInObj); cleanup: Tcl_Close(interp, chan); CleanupPNGImage(&png); return result; @@ -3534,17 +3802,17 @@ */ static int StringWritePNG( Tcl_Interp *interp, - Tcl_Obj *fmtObj, + TCL_UNUSED(Tcl_Obj *), + Tcl_Obj *metadataInObj, Tk_PhotoImageBlock *blockPtr) { Tcl_Obj *resultObj = Tcl_NewObj(); PNGImage png; int result = TCL_ERROR; - (void)fmtObj; /* * Initalize PNGImage instance for encoding. */ @@ -3556,11 +3824,11 @@ /* * Write the raw PNG data into the prepared Tcl_Obj buffer. Set the result * back to the interpreter if successful. */ - result = EncodePNG(interp, blockPtr, &png); + result = EncodePNG(interp, blockPtr, &png, metadataInObj); if (TCL_OK == result) { Tcl_SetObjResult(interp, png.objDataPtr); } Index: generic/tkImgPPM.c ================================================================== --- generic/tkImgPPM.c +++ generic/tkImgPPM.c @@ -1,12 +1,12 @@ /* * tkImgPPM.c -- * * A photo image file handler for PPM (Portable PixMap) files. * - * Copyright (c) 1994 The Australian National University. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Australian National University. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), @@ -199,11 +199,11 @@ destX + width, destY + height) != TCL_OK) { return TCL_ERROR; } if (srcY > 0) { - Tcl_Seek(chan, (Tcl_WideInt)(srcY * block.pitch), SEEK_CUR); + Tcl_Seek(chan, (long long)srcY * block.pitch, SEEK_CUR); } nLines = (MAX_MEMORY + block.pitch - 1) / block.pitch; if (nLines > height) { nLines = height; @@ -765,11 +765,11 @@ char buffer[BUFFER_SIZE], c; int i, numFields, type = 0; TkSizeT dataSize; unsigned char *dataBuffer; - dataBuffer = TkGetByteArrayFromObj(dataPtr, &dataSize); + dataBuffer = Tcl_GetByteArrayFromObj(dataPtr, &dataSize); /* * Read 4 space-separated fields from the string, ignoring comments (any * line that starts with "#"). */ Index: generic/tkImgPhInstance.c ================================================================== --- generic/tkImgPhInstance.c +++ generic/tkImgPhInstance.c @@ -3,14 +3,14 @@ * * Implements the rendering of images of type "photo" for Tk. Photo * images are stored in full color (32 bits per pixel including alpha * channel) and displayed using dithering if necessary. * - * Copyright (c) 1994 The Australian National University. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002-2008 Donal K. Fellows - * Copyright (c) 2003 ActiveState Corporation. + * Copyright © 1994 The Australian National University. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2002-2008 Donal K. Fellows + * Copyright © 2003 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), @@ -36,11 +36,11 @@ /* * Forward declarations */ -#ifndef TKPUTIMAGE_CAN_BLEND +#ifndef TK_CAN_RENDER_RGBA static void BlendComplexAlpha(XImage *bgImg, PhotoInstance *iPtr, int xOffset, int yOffset, int width, int height); #endif static int IsValidPalette(PhotoInstance *instancePtr, const char *palette); @@ -414,11 +414,11 @@ * * Note that Win32 pre-defines those operations that we really need. * *---------------------------------------------------------------------- */ -#ifndef TKPUTIMAGE_CAN_BLEND +#ifndef TK_CAN_RENDER_RGBA #ifndef _WIN32 #define GetRValue(rgb) (UCHAR(((rgb) & red_mask) >> red_shift)) #define GetGValue(rgb) (UCHAR(((rgb) & green_mask) >> green_shift)) #define GetBValue(rgb) (UCHAR(((rgb) & blue_mask) >> blue_shift)) #define RGB(r, g, b) ((unsigned)( \ @@ -580,11 +580,11 @@ } } } #undef ALPHA_BLEND } -#endif /* TKPUTIMAGE_CAN_BLEND */ +#endif /* TK_CAN_RENDER_RGBA */ /* *---------------------------------------------------------------------- * * TkImgPhotoDisplay -- @@ -612,11 +612,11 @@ * draw. */ int drawableX,int drawableY)/* Coordinates within drawable that correspond * to imageX and imageY. */ { PhotoInstance *instancePtr = (PhotoInstance *)clientData; -#ifndef TKPUTIMAGE_CAN_BLEND +#ifndef TK_CAN_RENDER_RGBA XVisualInfo visInfo = instancePtr->visualInfo; #endif /* * If there's no pixmap, it means that an error occurred while creating @@ -625,26 +625,28 @@ if (instancePtr->pixels == None) { return; } -#ifdef TKPUTIMAGE_CAN_BLEND +#ifdef TK_CAN_RENDER_RGBA + /* - * If TkPutImage can handle RGBA Ximages directly there is + * We can use TkpPutRGBAImage to render RGBA Ximages directly so there is * no need to call XGetImage or to do the Porter-Duff compositing by hand. */ unsigned char *rgbaPixels = instancePtr->modelPtr->pix32; XImage *photo = XCreateImage(display, NULL, 32, ZPixmap, 0, (char*)rgbaPixels, (unsigned int)instancePtr->width, (unsigned int)instancePtr->height, 0, (unsigned int)(4 * instancePtr->width)); - TkPutImage(NULL, 0, display, drawable, instancePtr->gc, + TkpPutRGBAImage(display, drawable, instancePtr->gc, photo, imageX, imageY, drawableX, drawableY, (unsigned int) width, (unsigned int) height); photo->data = NULL; XDestroyImage(photo); + #else if ((instancePtr->modelPtr->flags & COMPLEX_ALPHA) && visInfo.depth >= 15 && (visInfo.c_class == DirectColor || visInfo.c_class == TrueColor)) { Index: generic/tkImgPhoto.c ================================================================== --- generic/tkImgPhoto.c +++ generic/tkImgPhoto.c @@ -3,14 +3,14 @@ * * Implements images of type "photo" for Tk. Photo images are stored in * full color (32 bits per pixel including alpha channel) and displayed * using dithering if necessary. * - * Copyright (c) 1994 The Australian National University. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002-2003 Donal K. Fellows - * Copyright (c) 2003 ActiveState Corporation. + * Copyright © 1994 The Australian National University. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2002-2003 Donal K. Fellows + * Copyright © 2003 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), @@ -37,10 +37,11 @@ int subsampleX, subsampleY; /* Values specified for -subsample option. */ Tcl_Obj *format; /* Value specified for -format option. */ XColor *background; /* Value specified for -background option. */ int compositingRule; /* Value specified for -compositingrule * option. */ + Tcl_Obj *metadata; /* Value specified for -metadata option. */ }; /* * Bit definitions for use with ParseSubcommandOptions: each bit is set in the * allowedOptions parameter on a call to ParseSubcommandOptions if that option @@ -52,10 +53,11 @@ * OPT_BACKGROUND: Set if -format option allowed/specified. * OPT_COMPOSITE: Set if -compositingrule option allowed/spec'd. * OPT_FORMAT: Set if -format option allowed/specified. * OPT_FROM: Set if -from option allowed/specified. * OPT_GRAYSCALE: Set if -grayscale option allowed/specified. + * OPT_METADATA: Set if -metadata option allowed/specified. * OPT_SHRINK: Set if -shrink option allowed/specified. * OPT_SUBSAMPLE: Set if -subsample option allowed/spec'd. * OPT_TO: Set if -to option allowed/specified. * OPT_WITHALPHA: Set if -withalpha option allowed/specified. * OPT_ZOOM: Set if -zoom option allowed/specified. @@ -65,15 +67,16 @@ #define OPT_BACKGROUND 2 #define OPT_COMPOSITE 4 #define OPT_FORMAT 8 #define OPT_FROM 0x10 #define OPT_GRAYSCALE 0x20 -#define OPT_SHRINK 0x40 -#define OPT_SUBSAMPLE 0x80 -#define OPT_TO 0x100 -#define OPT_WITHALPHA 0x200 -#define OPT_ZOOM 0x400 +#define OPT_METADATA 0x40 +#define OPT_SHRINK 0x80 +#define OPT_SUBSAMPLE 0x100 +#define OPT_TO 0x200 +#define OPT_WITHALPHA 0x400 +#define OPT_ZOOM 0x800 /* * List of option names. The order here must match the order of declarations * of the OPT_* constants above. */ @@ -83,10 +86,11 @@ "-background", "-compositingrule", "-format", "-from", "-grayscale", + "-metadata", "-shrink", "-subsample", "-to", "-withalpha", "-zoom", @@ -138,10 +142,13 @@ #if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 Tk_PhotoImageFormat *oldFormatList; /* Pointer to the first in the list of known * photo image formats.*/ #endif + Tk_PhotoImageFormatVersion3 *formatListVersion3; + /* Pointer to the first in the list of known + * photo image formats in Version3 format.*/ int initialized; /* Set to 1 if we've initialized the * structure. */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -193,15 +200,21 @@ static char * ImgGetPhoto(PhotoModel *modelPtr, Tk_PhotoImageBlock *blockPtr, struct SubcommandOptions *optPtr); static int MatchFileFormat(Tcl_Interp *interp, Tcl_Channel chan, const char *fileName, Tcl_Obj *formatString, + Tcl_Obj *metadataInObj, + Tcl_Obj *metadataOutObj, Tk_PhotoImageFormat **imageFormatPtr, + Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr, int *widthPtr, int *heightPtr, int *oldformat); static int MatchStringFormat(Tcl_Interp *interp, Tcl_Obj *data, Tcl_Obj *formatString, + Tcl_Obj *metadataInObj, + Tcl_Obj *metadataOutObj, Tk_PhotoImageFormat **imageFormatPtr, + Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr, int *widthPtr, int *heightPtr, int *oldformat); static const char * GetExtension(const char *path); /* *---------------------------------------------------------------------- @@ -222,10 +235,11 @@ static void PhotoFormatThreadExitProc( TCL_UNUSED(void *)) /* not used */ { Tk_PhotoImageFormat *freePtr; + Tk_PhotoImageFormatVersion3 *freePtrVersion3; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); #if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 while (tsdPtr->oldFormatList != NULL) { @@ -238,16 +252,23 @@ freePtr = tsdPtr->formatList; tsdPtr->formatList = tsdPtr->formatList->nextPtr; ckfree((char *)freePtr->name); ckfree(freePtr); } + while (tsdPtr->formatListVersion3 != NULL) { + freePtrVersion3 = tsdPtr->formatListVersion3; + tsdPtr->formatListVersion3 = tsdPtr->formatListVersion3->nextPtr; + ckfree((char *)freePtrVersion3->name); + ckfree(freePtrVersion3); + } } /* *---------------------------------------------------------------------- * - * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat -- + * Tk_CreateOldPhotoImageFormat, Tk_CreatePhotoImageFormat, + * Tk_CreatePhotoImageFormatVersion3 -- * * This function is invoked by an image file handler to register a new * photo image format and the functions that handle the new format. The * function is typically invoked during Tcl_AppInit. * @@ -314,10 +335,36 @@ copyPtr->name = name; copyPtr->nextPtr = tsdPtr->formatList; tsdPtr->formatList = copyPtr; } } +void +Tk_CreatePhotoImageFormatVersion3( + const Tk_PhotoImageFormatVersion3 *formatPtr) + /* Structure describing the format. All of the + * fields except "nextPtr" must be filled in + * by caller. */ +{ + Tk_PhotoImageFormatVersion3 *copyPtr; + char *name; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + Tcl_CreateThreadExitHandler(PhotoFormatThreadExitProc, NULL); + } + copyPtr = (Tk_PhotoImageFormatVersion3 *) + ckalloc(sizeof(Tk_PhotoImageFormatVersion3)); + *copyPtr = *formatPtr; + /* for compatibility with aMSN: make a copy of formatPtr->name */ + name = (char *)ckalloc(strlen(formatPtr->name) + 1); + strcpy(name, formatPtr->name); + copyPtr->name = name; + copyPtr->nextPtr = tsdPtr->formatListVersion3; + tsdPtr->formatListVersion3 = copyPtr; +} /* *---------------------------------------------------------------------- * * ImgPhotoCreate -- @@ -417,10 +464,11 @@ int result, index, x, y, width, height; struct SubcommandOptions options; unsigned char *pixelPtr; Tk_PhotoImageBlock block; Tk_PhotoImageFormat *imageFormat; + Tk_PhotoImageFormatVersion3 *imageFormatVersion3; TkSizeT length; int imageWidth, imageHeight, matched, oldformat = 0; Tcl_Channel chan; Tk_PhotoHandle srcHandle; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) @@ -455,18 +503,22 @@ if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); return TCL_ERROR; } - arg = TkGetStringFromObj(objv[2], &length); + arg = Tcl_GetStringFromObj(objv[2], &length); if (strncmp(arg,"-data", length) == 0) { if (modelPtr->dataString) { Tcl_SetObjResult(interp, modelPtr->dataString); } } else if (strncmp(arg,"-format", length) == 0) { if (modelPtr->format) { Tcl_SetObjResult(interp, modelPtr->format); + } + } else if (strncmp(arg, "-metadata", length) == 0) { + if (modelPtr->metadata) { + Tcl_SetObjResult(interp, modelPtr->metadata); } } else { Tk_ConfigureValue(interp, Tk_MainWindow(interp), configSpecs, (char *) modelPtr, Tcl_GetString(objv[2]), 0); } @@ -497,18 +549,25 @@ subobj = Tcl_NewStringObj("-format {} {} {}", 16); if (modelPtr->format) { Tcl_ListObjAppendElement(NULL, subobj, modelPtr->format); } else { Tcl_AppendStringsToObj(subobj, " {}", NULL); + } + Tcl_ListObjAppendElement(interp, obj, subobj); + subobj = Tcl_NewStringObj("-metadata {} {} {}", 16); + if (modelPtr->metadata) { + Tcl_ListObjAppendElement(NULL, subobj, modelPtr->metadata); + } else { + Tcl_AppendStringsToObj(subobj, " {}", NULL); } Tcl_ListObjAppendElement(interp, obj, subobj); Tcl_ListObjAppendList(interp, obj, Tcl_GetObjResult(interp)); Tcl_SetObjResult(interp, obj); return TCL_OK; } else if (objc == 3) { - const char *arg = TkGetStringFromObj(objv[2], &length); + const char *arg = Tcl_GetStringFromObj(objv[2], &length); if (length > 1 && !strncmp(arg, "-data", length)) { Tcl_AppendResult(interp, "-data {} {} {}", NULL); if (modelPtr->dataString) { /* @@ -529,10 +588,24 @@ * TODO: Modifying result is bad! */ Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), modelPtr->format); + } else { + Tcl_AppendResult(interp, " {}", NULL); + } + return TCL_OK; + } else if (length > 1 && + !strncmp(arg, "-metadata", length)) { + Tcl_AppendResult(interp, "-metadata {} {} {}", NULL); + if (modelPtr->metadata) { + /* + * TODO: Modifying result is bad! + */ + + Tcl_ListObjAppendElement(NULL, Tcl_GetObjResult(interp), + modelPtr->metadata); } else { Tcl_AppendResult(interp, " {}", NULL); } return TCL_OK; } else { @@ -676,25 +749,29 @@ return result; case PHOTO_DATA: { char *data = NULL; Tcl_Obj *freeObj = NULL; + Tcl_Obj *metadataIn; /* * photo data command - first parse and check any options given. */ Tk_ImageStringWriteProc *stringWriteProc = NULL; + Tk_ImageStringWriteProcVersion3 *stringWriteProcVersion3 = NULL; index = 1; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; + options.metadata = NULL; options.fromX = 0; options.fromY = 0; if (ParseSubcommandOptions(&options, interp, - OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND, + OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND + | OPT_METADATA, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "?-option value ...?"); @@ -720,10 +797,20 @@ } if (!(options.options & OPT_FORMAT)) { options.format = Tcl_NewStringObj("default", -1); freeObj = options.format; } + + /* + * Use argument metadata if specified, otherwise the master metadata + */ + + if (NULL != options.metadata) { + metadataIn = options.metadata; + } else { + metadataIn = modelPtr->metadata; + } /* * Search for an appropriate image string format handler. */ @@ -755,26 +842,46 @@ } } } #endif if (stringWriteProc == NULL) { + oldformat = 0; + for (imageFormatVersion3 = tsdPtr->formatListVersion3; + imageFormatVersion3 != NULL; + imageFormatVersion3 = imageFormatVersion3->nextPtr) { + if ((strncasecmp(Tcl_GetString(options.format), + imageFormatVersion3->name, + strlen(imageFormatVersion3->name)) == 0)) { + matched = 1; + if (imageFormatVersion3->stringWriteProc != NULL) { + stringWriteProcVersion3 = + imageFormatVersion3->stringWriteProc; + break; + } + } + } + } + if (stringWriteProc == NULL && stringWriteProcVersion3 == NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image string format \"%s\" is %s", - Tcl_GetString(options.format), - (matched ? "not supported" : "unknown"))); + "image string format \"%s\" is %s", + Tcl_GetString(options.format), + (matched ? "not supported" : "unknown"))); Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", - Tcl_GetString(options.format), NULL); + Tcl_GetString(options.format), NULL); goto dataErrorExit; } /* * Call the handler's string write function to write out the image. */ data = ImgGetPhoto(modelPtr, &block, &options); - if (oldformat) { + if (stringWriteProc == NULL) { + result = (stringWriteProcVersion3)(interp, + options.format, metadataIn, &block); + } else if (oldformat) { Tcl_DString buffer; typedef int (*OldStringWriteProc)(Tcl_Interp *interp, Tcl_DString *dataPtr, const char *formatString, Tk_PhotoImageBlock *blockPtr); @@ -877,11 +984,13 @@ index = 2; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; - if (ParseSubcommandOptions(&options, interp, OPT_TO|OPT_FORMAT, + options.metadata = NULL; + if (ParseSubcommandOptions(&options, interp, + OPT_TO|OPT_FORMAT|OPT_METADATA, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "data ?-option value ...?"); @@ -890,12 +999,14 @@ /* * See if there's a format that can read the data */ - if (MatchStringFormat(interp, objv[2], options.format, &imageFormat, - &imageWidth, &imageHeight, &oldformat) != TCL_OK) { + if (MatchStringFormat(interp, objv[2], options.format, + options.metadata, NULL, &imageFormat, + &imageFormatVersion3, &imageWidth, &imageHeight, &oldformat) + != TCL_OK) { return TCL_ERROR; } if (!(options.options & OPT_TO) || (options.toX2 < 0)) { options.toX2 = options.toX + imageWidth; @@ -914,16 +1025,29 @@ format = (Tcl_Obj *) Tcl_GetString(format); } data = (Tcl_Obj *) Tcl_GetString(data); } - if (imageFormat->stringReadProc(interp, data, format, - (Tk_PhotoHandle) modelPtr, options.toX, options.toY, - options.toX2 - options.toX, - options.toY2 - options.toY, 0, 0) != TCL_OK) { - return TCL_ERROR; + if (imageFormat != NULL) { + if (imageFormat->stringReadProc(interp, data, format, + (Tk_PhotoHandle) modelPtr, options.toX, options.toY, + options.toX2 - options.toX, + options.toY2 - options.toY, 0, 0) != TCL_OK) { + return TCL_ERROR; + } + } else { + if (imageFormatVersion3->stringReadProc(interp, data, format, + options.metadata, + (Tk_PhotoHandle) modelPtr, options.toX, options.toY, + options.toX2 - options.toX, + options.toY2 - options.toY, 0, 0, + NULL) + != TCL_OK) { + return TCL_ERROR; + } } + /* * SB: is the next line really needed? The stringReadProc * writes image data with Tk_PhotoPutBlock(), which in turn * takes care to notify the changed image and to set/unset the * IMAGE_CHANGED bit. @@ -941,12 +1065,13 @@ index = 2; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; + options.metadata = NULL; if (ParseSubcommandOptions(&options, interp, - OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK, + OPT_FORMAT | OPT_FROM | OPT_TO | OPT_SHRINK | OPT_METADATA, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "fileName ?-option value ...?"); @@ -983,14 +1108,16 @@ Tcl_Close(NULL, chan); return TCL_ERROR; } if (MatchFileFormat(interp, chan, - Tcl_GetString(options.name), options.format, &imageFormat, - &imageWidth, &imageHeight, &oldformat) != TCL_OK) { - Tcl_Close(NULL, chan); - return TCL_ERROR; + Tcl_GetString(options.name), options.format, + options.metadata, NULL, &imageFormat, + &imageFormatVersion3, &imageWidth, &imageHeight, &oldformat) + != TCL_OK) { + result = TCL_ERROR; + goto readCleanup; } /* * Check the values given for the -from option. */ @@ -1000,12 +1127,12 @@ || (options.fromY2 > imageHeight)) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "coordinates for -from option extend outside source image", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "BAD_FROM", NULL); - Tcl_Close(NULL, chan); - return TCL_ERROR; + result = TCL_ERROR; + goto readCleanup; } if (!(options.options & OPT_FROM) || (options.fromX2 < 0)) { width = imageWidth - options.fromX; height = imageHeight - options.fromY; } else { @@ -1022,12 +1149,12 @@ options.toY + height) != TCL_OK) { Tcl_ResetResult(interp); Tcl_SetObjResult(interp, Tcl_NewStringObj( TK_PHOTO_ALLOC_FAILURE_MESSAGE, -1)); Tcl_SetErrorCode(interp, "TK", "MALLOC", NULL); - Tcl_Close(NULL, chan); - return TCL_ERROR; + result = TCL_ERROR; + goto readCleanup; } } /* * Call the handler's file read function to read the data into the @@ -1036,14 +1163,23 @@ format = options.format; if (oldformat && format) { format = (Tcl_Obj *) Tcl_GetString(format); } - result = imageFormat->fileReadProc(interp, chan, - Tcl_GetString(options.name), - format, (Tk_PhotoHandle) modelPtr, options.toX, - options.toY, width, height, options.fromX, options.fromY); + if (imageFormat != NULL) { + result = imageFormat->fileReadProc(interp, chan, + Tcl_GetString(options.name), + format, (Tk_PhotoHandle) modelPtr, options.toX, + options.toY, width, height, options.fromX, options.fromY); + } else { + result = imageFormatVersion3->fileReadProc(interp, chan, + Tcl_GetString(options.name), + format, options.metadata, (Tk_PhotoHandle) modelPtr, + options.toX, options.toY, width, height, options.fromX, + options.fromY, NULL); + } +readCleanup: if (chan != NULL) { Tcl_Close(NULL, chan); } return result; } @@ -1269,11 +1405,11 @@ } case PHOTO_WRITE: { char *data; const char *fmtString; - Tcl_Obj *format; + Tcl_Obj *format, *metadataIn; int usedExt; /* * Prevent file system access in safe interpreters. */ @@ -1291,12 +1427,14 @@ index = 2; memset(&options, 0, sizeof(options)); options.name = NULL; options.format = NULL; + options.metadata = NULL; if (ParseSubcommandOptions(&options, interp, - OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND, + OPT_FORMAT | OPT_FROM | OPT_GRAYSCALE | OPT_BACKGROUND + | OPT_METADATA, &index, objc, objv) != TCL_OK) { return TCL_ERROR; } if ((options.name == NULL) || (index < objc)) { Tcl_WrongNumArgs(interp, 2, objv, "fileName ?-option value ...?"); @@ -1328,17 +1466,29 @@ } else { fmtString = Tcl_GetString(options.format); usedExt = 0; } + + /* + * Use argument metadata if specified, otherwise the master metadata + */ + + if (NULL != options.metadata) { + metadataIn = options.metadata; + } else { + metadataIn = modelPtr->metadata; + } + /* * Search for an appropriate image file format handler, and give an * error if none is found. */ matched = 0; redoFormatLookup: + imageFormatVersion3 = NULL; for (imageFormat = tsdPtr->formatList; imageFormat != NULL; imageFormat = imageFormat->nextPtr) { if ((fmtString == NULL) || (strncasecmp(fmtString, imageFormat->name, strlen(imageFormat->name)) == 0)) { @@ -1362,10 +1512,25 @@ } } } } #endif + if (imageFormat == NULL) { + oldformat = 0; + for (imageFormatVersion3 = tsdPtr->formatListVersion3; + imageFormatVersion3 != NULL; + imageFormatVersion3 = imageFormatVersion3->nextPtr) { + if ((fmtString == NULL) + || (strncasecmp(fmtString, imageFormatVersion3->name, + strlen(imageFormatVersion3->name)) == 0)) { + matched = 1; + if (imageFormatVersion3->fileWriteProc != NULL) { + break; + } + } + } + } if (usedExt && !matched) { /* * If we didn't find one and we're using file extensions as the * basis for the guessing, go back and look again without * prejudice. Supports old broken code. @@ -1373,11 +1538,11 @@ usedExt = 0; fmtString = NULL; goto redoFormatLookup; } - if (imageFormat == NULL) { + if (imageFormat == NULL && imageFormatVersion3 == NULL) { if (fmtString == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "no available image file format has file writing" " capability", -1)); } else if (!matched) { @@ -1400,12 +1565,18 @@ data = ImgGetPhoto(modelPtr, &block, &options); format = options.format; if (oldformat && format) { format = (Tcl_Obj *) Tcl_GetString(options.format); } - result = imageFormat->fileWriteProc(interp, - Tcl_GetString(options.name), format, &block); + if (imageFormat != NULL) { + result = imageFormat->fileWriteProc(interp, + Tcl_GetString(options.name), format, &block); + } else { + result = imageFormatVersion3->fileWriteProc(interp, + Tcl_GetString(options.name), format, metadataIn, + &block); + } if (options.background) { Tk_FreeColor(options.background); } if (data) { ckfree(data); @@ -1453,12 +1624,12 @@ * * ParseSubcommandOptions -- * * This function is invoked to process one of the options which may be * specified for the photo image subcommands, namely, -from, -to, -zoom, - * -subsample, -format, -shrink, -compositingrule, -alpha, -boolean and - * -withalpha. + * -subsample, -format, -shrink, -compositingrule, -alpha, -boolean, + * -withalpha and -metadata. * Parsing starts at the index in *optIndexPtr and stops at the end of * objv[] or at the first value that does not belong to an option. * * Results: * A standard Tcl result. @@ -1501,11 +1672,11 @@ /* * We can have one value specified without an option; it goes into * optPtr->name. */ - expandedOption = option = TkGetStringFromObj(objv[index], &length); + expandedOption = option = Tcl_GetStringFromObj(objv[index], &length); if (option[0] != '-') { if (optPtr->name == NULL) { optPtr->name = objv[index]; continue; } @@ -1572,10 +1743,21 @@ if (index + 1 >= objc) { goto oneValueRequired; } *optIndexPtr = ++index; optPtr->format = objv[index]; + } else if (bit == OPT_METADATA) { + /* + * The -metadata option takes a single dict value. Note that + * parsing this is outside the scope of this function. + */ + + if (index + 1 >= objc) { + goto oneValueRequired; + } + *optIndexPtr = ++index; + optPtr->metadata = objv[index]; } else if (bit == OPT_COMPOSITE) { /* * The -compositingrule option takes a single value from a * well-known set. */ @@ -1768,22 +1950,24 @@ int flags) /* Flags to pass to Tk_ConfigureWidget, such * as TK_CONFIG_ARGV_ONLY. */ { PhotoInstance *instancePtr; const char *oldFileString, *oldPaletteString; - Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL; + Tcl_Obj *oldData, *data = NULL, *oldFormat, *format = NULL, + *metadataInObj = NULL, *metadataOutObj = NULL; Tcl_Obj *tempdata, *tempformat; TkSizeT length; int i, j, result, imageWidth, imageHeight, oldformat; double oldGamma; Tcl_Channel chan; Tk_PhotoImageFormat *imageFormat; + Tk_PhotoImageFormatVersion3 *imageFormatVersion3; const char **args; args = (const char **)ckalloc((objc + 1) * sizeof(char *)); for (i = 0, j = 0; i < objc; i++,j++) { - args[j] = TkGetStringFromObj(objv[i], &length); + args[j] = Tcl_GetStringFromObj(objv[i], &length); if ((length > 1) && (args[j][0] == '-')) { if ((args[j][1] == 'd') && !strncmp(args[j], "-data", length)) { if (++i < objc) { data = objv[i]; @@ -1806,10 +1990,23 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj( "value for \"-format\" missing", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", "MISSING_VALUE", NULL); return TCL_ERROR; + } + } else if ((args[j][1] == 'm') && + !strncmp(args[j], "-metadata", length)) { + if (++i < objc) { + metadataInObj = objv[i]; + j--; + } else { + ckfree(args); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "value for \"-metadata\" missing", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "MISSING_VALUE", NULL); + return TCL_ERROR; } } } } @@ -1846,11 +2043,11 @@ goto errorExit; } ckfree(args); /* - * Regard the empty string for -file, -data or -format as the null value. + * Regard the empty string for -file, -data, -format or -metadata as the null value. */ if ((modelPtr->fileString != NULL) && (modelPtr->fileString[0] == 0)) { ckfree(modelPtr->fileString); modelPtr->fileString = NULL; @@ -1860,11 +2057,11 @@ * Force into ByteArray format, which most (all) image handlers will * use anyway. Empty length means ignore the -data option. */ TkSizeT bytesize; - (void) TkGetByteArrayFromObj(data, &bytesize); + (void) Tcl_GetByteArrayFromObj(data, &bytesize); if (bytesize) { Tcl_IncrRefCount(data); } else { data = NULL; } @@ -1888,10 +2085,36 @@ if (modelPtr->format) { Tcl_DecrRefCount(modelPtr->format); } modelPtr->format = format; } + if (metadataInObj) { + /* + * Make -metadata a dict. + * Take also empty metadatas as this may be a sign to replace + * existing metadata. + */ + int dictSize; + + if (TCL_OK != Tcl_DictObjSize(interp,metadataInObj, &dictSize)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "value for \"-metadata\" not a dict", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "UNRECOGNIZED_DATA", NULL); + return TCL_ERROR; + } + + if (dictSize > 0) { + Tcl_IncrRefCount(metadataInObj); + } else { + metadataInObj = NULL; + } + if (modelPtr->metadata) { + Tcl_DecrRefCount(modelPtr->metadata); + } + modelPtr->metadata = metadataInObj; + } /* * Set the image to the user-requested size, if any, and make sure storage * is correctly allocated for this image. */ @@ -1909,10 +2132,11 @@ */ if ((modelPtr->fileString != NULL) && ((modelPtr->fileString != oldFileString) || (modelPtr->format != oldFormat))) { + /* * Prevent file system access in a safe interpreter. */ if (Tcl_IsSafe(interp)) { @@ -1927,19 +2151,27 @@ chan = Tcl_OpenFileChannel(interp, modelPtr->fileString, "r", 0); if (chan == NULL) { goto errorExit; } + /* + * Flag that we want the metadata result dict + */ + + metadataOutObj = Tcl_NewDictObj(); + Tcl_IncrRefCount(metadataOutObj); + /* * -translation binary also sets -encoding binary */ if ((Tcl_SetChannelOption(interp, chan, "-translation", "binary") != TCL_OK) || (MatchFileFormat(interp, chan, modelPtr->fileString, - modelPtr->format, &imageFormat, &imageWidth, - &imageHeight, &oldformat) != TCL_OK)) { + modelPtr->format, modelPtr->metadata, metadataOutObj, + &imageFormat, &imageFormatVersion3, + &imageWidth, &imageHeight, &oldformat) != TCL_OK)) { Tcl_Close(NULL, chan); goto errorExit; } result = ImgPhotoSetSize(modelPtr, imageWidth, imageHeight); if (result != TCL_OK) { @@ -1951,13 +2183,23 @@ } tempformat = modelPtr->format; if (oldformat && tempformat) { tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); } - result = imageFormat->fileReadProc(interp, chan, - modelPtr->fileString, tempformat, (Tk_PhotoHandle) modelPtr, - 0, 0, imageWidth, imageHeight, 0, 0); + if (imageFormat != NULL) { + result = imageFormat->fileReadProc(interp, chan, + modelPtr->fileString, tempformat, + (Tk_PhotoHandle) modelPtr, + 0, 0, imageWidth, imageHeight, 0, 0); + } else { + result = imageFormatVersion3->fileReadProc(interp, chan, + modelPtr->fileString, tempformat, modelPtr->metadata, + (Tk_PhotoHandle) modelPtr, + 0, 0, imageWidth, imageHeight, 0, 0, + metadataOutObj); + } + Tcl_Close(NULL, chan); if (result != TCL_OK) { goto errorExit; } @@ -1967,12 +2209,20 @@ if ((modelPtr->fileString == NULL) && (modelPtr->dataString != NULL) && ((modelPtr->dataString != oldData) || (modelPtr->format != oldFormat))) { + /* + * Flag that we want the metadata result dict + */ + + metadataOutObj = Tcl_NewDictObj(); + Tcl_IncrRefCount(metadataOutObj); + if (MatchStringFormat(interp, modelPtr->dataString, - modelPtr->format, &imageFormat, &imageWidth, + modelPtr->format, modelPtr->metadata, metadataOutObj, + &imageFormat, &imageFormatVersion3, &imageWidth, &imageHeight, &oldformat) != TCL_OK) { goto errorExit; } if (ImgPhotoSetSize(modelPtr, imageWidth, imageHeight) != TCL_OK) { Tcl_SetObjResult(interp, Tcl_NewStringObj( @@ -1986,19 +2236,70 @@ if (tempformat) { tempformat = (Tcl_Obj *) Tcl_GetString(tempformat); } tempdata = (Tcl_Obj *) Tcl_GetString(tempdata); } - if (imageFormat->stringReadProc(interp, tempdata, tempformat, - (Tk_PhotoHandle) modelPtr, 0, 0, imageWidth, imageHeight, - 0, 0) != TCL_OK) { - goto errorExit; + if (imageFormat != NULL) { + if (imageFormat->stringReadProc(interp, tempdata, tempformat, + (Tk_PhotoHandle) modelPtr, 0, 0, imageWidth, imageHeight, + 0, 0) != TCL_OK) { + goto errorExit; + } + } else { + if (imageFormatVersion3->stringReadProc(interp, tempdata, tempformat, + modelPtr->metadata, (Tk_PhotoHandle) modelPtr, 0, 0, + imageWidth, imageHeight, 0, 0, metadataOutObj) != TCL_OK) { + goto errorExit; + } } Tcl_ResetResult(interp); modelPtr->flags |= IMAGE_CHANGED; } + + /* + * Merge driver returned metadata and master metadata + */ + if (metadataOutObj != NULL) { + int dictSize; + if (TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "driver metadata not a dict", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "UNRECOGNIZED_DATA", NULL); + goto errorExit; + } + if (dictSize > 0) { + + /* + * We have driver return metadata + */ + + if (modelPtr->metadata == NULL) { + modelPtr->metadata = metadataOutObj; + metadataOutObj = NULL; + } else { + Tcl_DictSearch search; + Tcl_Obj *key, *value; + int done; + + if (Tcl_IsShared(modelPtr->metadata)) { + Tcl_DecrRefCount(modelPtr->metadata); + modelPtr->metadata = Tcl_DuplicateObj(modelPtr->metadata); + Tcl_IncrRefCount(modelPtr->metadata); + } + + if (Tcl_DictObjFirst(interp, metadataOutObj, &search, &key, + &value, &done) != TCL_OK) { + goto errorExit; + } + for (; !done ; Tcl_DictObjNext(&search, &key, &value, &done)) { + Tcl_DictObjPut(interp, modelPtr->metadata, key, value); + } + } + } + } /* * Enforce a reasonable value for gamma. */ @@ -2034,10 +2335,13 @@ Tcl_DecrRefCount(oldData); } if (oldFormat != NULL) { Tcl_DecrRefCount(oldFormat); } + if (metadataOutObj != NULL) { + Tcl_DecrRefCount(metadataOutObj); + } ToggleComplexAlphaIfNeeded(modelPtr); return TCL_OK; @@ -2046,10 +2350,13 @@ Tcl_DecrRefCount(oldData); } if (oldFormat != NULL) { Tcl_DecrRefCount(oldFormat); } + if (metadataOutObj != NULL) { + Tcl_DecrRefCount(metadataOutObj); + } return TCL_ERROR; } /* *---------------------------------------------------------------------- @@ -2143,10 +2450,13 @@ Tcl_DecrRefCount(modelPtr->dataString); } if (modelPtr->format != NULL) { Tcl_DecrRefCount(modelPtr->format); } + if (modelPtr->metadata != NULL) { + Tcl_DecrRefCount(modelPtr->metadata); + } Tk_FreeOptions(configSpecs, (char *) modelPtr, NULL, 0); ckfree(modelPtr); } /* @@ -2379,13 +2689,13 @@ * format string is provided, only handlers whose names match a prefix of * the format string are tried. * * Results: * A standard TCL return value. If the return value is TCL_OK, a pointer - * to the image format record is returned in *imageFormatPtr, and the - * width and height of the image are returned in *widthPtr and - * *heightPtr. + * to the image format record is returned in *imageFormatPtr or + * *imageFormatVersion3Ptr, and the width and height of the image are + * returned in *widthPtr and *heightPtr. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -2395,21 +2705,29 @@ MatchFileFormat( Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ Tcl_Channel chan, /* The image file, open for reading. */ const char *fileName, /* The name of the image file. */ Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tcl_Obj *metadataInObj, /* User-specified metadata, may be NULL */ + Tcl_Obj *metadataOutObj, /* metadata to return, may be NULL */ Tk_PhotoImageFormat **imageFormatPtr, /* A pointer to the photo image format record - * is returned here. */ + * is returned here. For formatVersion3, this is + * set to NULL */ + Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr, + /* A pointer to the photo image formatVersion3 + * record is returned here. For non + * formatVersion3, this is set to NULL*/ int *widthPtr, int *heightPtr, /* The dimensions of the image are returned * here. */ int *oldformat) /* Returns 1 if the old image API is used. */ { int matched = 0; int useoldformat = 0; Tk_PhotoImageFormat *formatPtr; + Tk_PhotoImageFormatVersion3 *formatVersion3Ptr; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); const char *formatString = NULL; if (formatObj) { @@ -2488,31 +2806,101 @@ } } } #endif - if (formatPtr == NULL) { - if ((formatObj != NULL) && !matched) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "image file format \"%s\" is not supported", - formatString)); - Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", - formatString, NULL); - } else { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "couldn't recognize data in image file \"%s\"", - fileName)); - Tcl_SetErrorCode(interp, "TK", "PHOTO", "IMAGE", - "UNRECOGNIZED_DATA", NULL); - } - return TCL_ERROR; - } - - *imageFormatPtr = formatPtr; - *oldformat = useoldformat; - (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); - return TCL_OK; + /* + * For old and not version 3 format, exit now with success + */ + + if (formatPtr != NULL) { + *imageFormatPtr = formatPtr; + *imageFormatVersion3Ptr = NULL; + *oldformat = useoldformat; + (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); + return TCL_OK; + } + + /* + * Scan through the table of file format version 3 handlers to find one + * which can handle the image. + */ + + for (formatVersion3Ptr = tsdPtr->formatListVersion3; + formatVersion3Ptr != NULL; + formatVersion3Ptr = formatVersion3Ptr->nextPtr) { + if (formatObj != NULL) { + if (strncasecmp(formatString, + formatVersion3Ptr->name, strlen(formatVersion3Ptr->name)) + != 0) { + continue; + } + matched = 1; + if (formatVersion3Ptr->fileMatchProc == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "-file option isn't supported for %s images", + formatString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "NOT_FILE_FORMAT", NULL); + return TCL_ERROR; + } + } + if (formatVersion3Ptr->fileMatchProc != NULL) { + (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); + + if (formatVersion3Ptr->fileMatchProc(interp, chan, fileName, + formatObj, metadataInObj, widthPtr, heightPtr, + metadataOutObj)) { + if (*widthPtr < 1) { + *widthPtr = 1; + } + if (*heightPtr < 1) { + *heightPtr = 1; + } + *imageFormatVersion3Ptr = formatVersion3Ptr; + *imageFormatPtr = NULL; + *oldformat = 0; + (void) Tcl_Seek(chan, Tcl_LongAsWide(0L), SEEK_SET); + return TCL_OK; + } + + /* + * Check if driver has shared or changed the metadata Tcl object. + * In this case, release and recreate it. + */ + + if (metadataOutObj != NULL) { + int dictSize; + if (Tcl_IsShared(metadataOutObj) + || TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize) + || dictSize > 0) { + Tcl_DecrRefCount(metadataOutObj); + metadataOutObj = Tcl_NewDictObj(); + Tcl_IncrRefCount(metadataOutObj); + } + } + } + } + + /* + * No matching format found + */ + + if ((formatObj != NULL) && !matched) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "image file format \"%s\" is not supported", + formatString)); + Tcl_SetErrorCode(interp, "TK", "LOOKUP", "PHOTO_FORMAT", + formatString, NULL); + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "couldn't recognize data in image file \"%s\"", + fileName)); + Tcl_SetErrorCode(interp, "TK", "PHOTO", "IMAGE", + "UNRECOGNIZED_DATA", NULL); + } + return TCL_ERROR; } /* *---------------------------------------------------------------------- * @@ -2523,13 +2911,13 @@ * user-specified format string is provided, only handlers whose names * match a prefix of the format string are tried. * * Results: * A standard TCL return value. If the return value is TCL_OK, a pointer - * to the image format record is returned in *imageFormatPtr, and the - * width and height of the image are returned in *widthPtr and - * *heightPtr. + * to the image format record is returned in *imageFormatPtr or + * *imageFormatVersion3Ptr, and the width and height of the image are + * returned in *widthPtr and *heightPtr. * * Side effects: * None. * *---------------------------------------------------------------------- @@ -2538,20 +2926,28 @@ static int MatchStringFormat( Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ Tcl_Obj *data, /* Object containing the image data. */ Tcl_Obj *formatObj, /* User-specified format string, or NULL. */ + Tcl_Obj *metadataInObj, /* User-specified metadata, may be NULL */ + Tcl_Obj *metadataOutObj, /* metadata output dict, may be NULL */ Tk_PhotoImageFormat **imageFormatPtr, /* A pointer to the photo image format record - * is returned here. */ + * is returned here. For formatVersion3, this is + * set to NULL*/ + Tk_PhotoImageFormatVersion3 **imageFormatVersion3Ptr, + /* A pointer to the photo image formatVersion3 + * record is returned here. For non + * formatVersion3, this is set to NULL*/ int *widthPtr, int *heightPtr, /* The dimensions of the image are returned * here. */ int *oldformat) /* Returns 1 if the old image API is used. */ { int matched = 0, useoldformat = 0; Tk_PhotoImageFormat *formatPtr, *defaultFormatPtr = NULL; + Tk_PhotoImageFormatVersion3 *formatVersion3Ptr = NULL; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); const char *formatString = NULL; if (formatObj) { @@ -2639,10 +3035,57 @@ } } #endif if (formatPtr == NULL) { + useoldformat = 0; + for (formatVersion3Ptr = tsdPtr->formatListVersion3; + formatVersion3Ptr != NULL; + formatVersion3Ptr = formatVersion3Ptr->nextPtr) { + if (formatObj != NULL) { + if (strncasecmp(formatString, + formatVersion3Ptr->name, strlen(formatVersion3Ptr->name) + ) != 0) { + continue; + } + matched = 1; + if (formatVersion3Ptr->stringMatchProc == NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "-data option isn't supported for %s images", + formatString)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO", + "NOT_DATA_FORMAT", NULL); + return TCL_ERROR; + } + } + if ((formatVersion3Ptr->stringMatchProc != NULL) + && (formatVersion3Ptr->stringReadProc != NULL) + && formatVersion3Ptr->stringMatchProc(interp, data, + formatObj, metadataInObj, widthPtr, heightPtr, + metadataOutObj)) { + break; + } + + /* + * Check if driver has shared or changed the metadata tcl object. + * In this case, release and recreate it. + */ + + if (metadataOutObj != NULL) { + int dictSize; + if (Tcl_IsShared(metadataOutObj) + || TCL_OK != Tcl_DictObjSize(interp,metadataOutObj, &dictSize) + || dictSize > 0) { + Tcl_DecrRefCount(metadataOutObj); + metadataOutObj = Tcl_NewDictObj(); + Tcl_IncrRefCount(metadataOutObj); + } + } + } + } + + if (formatPtr == NULL && formatVersion3Ptr == NULL) { /* * Try the default format as last resort (only if no -format option * was passed). */ @@ -2679,10 +3122,11 @@ return TCL_ERROR; } } *imageFormatPtr = formatPtr; + *imageFormatVersion3Ptr = formatVersion3Ptr; *oldformat = useoldformat; /* * Some stringMatchProc might have left error messages and error codes in * interp. Clear them before return. @@ -4080,11 +4524,11 @@ /* *---------------------------------------------------------------------- * * Tk_PhotoPutBlock_NoComposite, Tk_PhotoPutZoomedBlock_NoComposite -- * - * These backward-compatability functions just exist to fill slots in stubs + * These backward-compatibility functions just exist to fill slots in stubs * table. For the behaviour of *_NoComposite, refer to the corresponding * function without the extra suffix, except that the compositing rule is * always "overlay" and the function always panics on memory-allocation * failure. * @@ -4121,11 +4565,11 @@ *---------------------------------------------------------------------- * * Tk_PhotoExpand_Panic, Tk_PhotoPutBlock_Panic, * Tk_PhotoPutZoomedBlock_Panic, Tk_PhotoSetSize_Panic * - * Backward compatability functions for preserving the old behaviour (i.e. + * Backward compatibility functions for preserving the old behaviour (i.e. * panic on memory allocation failure) so that extensions do not need to be * significantly updated to take account of TIP #116. These call the new * interface (i.e. the interface without the extra suffix), but panic if an * error condition is returned. * Index: generic/tkImgPhoto.h ================================================================== --- generic/tkImgPhoto.h +++ generic/tkImgPhoto.h @@ -1,14 +1,14 @@ /* * tkImgPhoto.h -- * * Declarations for images of type "photo" for Tk. * - * Copyright (c) 1994 The Australian National University. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2002-2008 Donal K. Fellows - * Copyright (c) 2003 ActiveState Corporation. + * Copyright © 1994 The Australian National University. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2002-2008 Donal K. Fellows + * Copyright © 2003 ActiveState Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * Author: Paul Mackerras (paulus@cs.anu.edu.au), @@ -157,10 +157,12 @@ double gamma; /* Display gamma value to correct for. */ char *fileString; /* Name of file to read into image. */ Tcl_Obj *dataString; /* Object to use as contents of image. */ Tcl_Obj *format; /* User-specified format of data in image file * or string value. */ + Tcl_Obj *metadata; /* User-specified metadata dict or read from + * image file */ unsigned char *pix32; /* Local storage for 32-bit image. */ int ditherX, ditherY; /* Location of first incorrectly dithered * pixel in image. */ TkRegion validRegion; /* Tk region indicating which parts of the * image have valid image data. */ Index: generic/tkImgSVGnano.c ================================================================== --- generic/tkImgSVGnano.c +++ generic/tkImgSVGnano.c @@ -1,14 +1,14 @@ /* * tkImgSVGnano.c * * A photo file handler for SVG files. * - * Copyright (c) 2013-14 Mikko Mononen memon@inside.org - * Copyright (c) 2018 Christian Gollwitzer auriocus@gmx.de - * Copyright (c) 2018 Christian Werner https://www.androwish.org/ - * Copyright (c) 2018 Rene Zaumseil r.zaumseil@freenet.de + * Copyright © 2013-14 Mikko Mononen memon@inside.org + * Copyright © 2018 Christian Gollwitzer auriocus@gmx.de + * Copyright © 2018 Christian Werner https://www.androwish.org/ + * Copyright © 2018 Rene Zaumseil r.zaumseil@freenet.de * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * * This handler is build using the original nanosvg library files from @@ -50,10 +50,12 @@ Tcl_DString formatString; NSVGimage *nsvgImage; RastOpts ropts; } NSVGcache; +static const void * MemMem(const void *haystack, size_t haysize, + const void *needle, size_t needlen); static int FileMatchSVG(Tcl_Channel chan, const char *fileName, Tcl_Obj *format, int *widthPtr, int *heightPtr, Tcl_Interp *interp); static int FileReadSVG(Tcl_Interp *interp, Tcl_Channel chan, const char *fileName, Tcl_Obj *format, @@ -99,10 +101,50 @@ }; /* *---------------------------------------------------------------------- * + * MemMem -- + * + * Like strstr() but operating on memory buffers with sizes. + * + *---------------------------------------------------------------------- + */ + +static const void * +MemMem(const void *haystack, size_t haylen, + const void *needle, size_t needlen) +{ + const void *hayend, *second, *p; + unsigned char first; + + if ((needlen <= 0) || (haylen < needlen)) { + return NULL; + } + hayend = (const void *) ((char *) haystack + haylen - needlen); + first = ((char *) needle)[0]; + second = (const void *) ((char *) needle + 1); + needlen -= 1; + while (haystack < hayend) { + p = memchr(haystack, first, (char *) hayend - (char *) haystack); + if (p == NULL) { + break; + } + if (needlen == 0) { + return p; + } + haystack = (const void *) ((char *) p + 1); + if (memcmp(second, haystack, needlen) == 0) { + return p; + } + } + return NULL; +} + +/* + *---------------------------------------------------------------------- + * * FileMatchSVG -- * * This function is invoked by the photo image type to see if a file * contains image data in SVG format. * @@ -130,16 +172,28 @@ RastOpts ropts; NSVGimage *nsvgImage; (void)fileName; CleanCache(interp); - if (Tcl_ReadChars(chan, dataObj, -1, 0) == TCL_IO_FAILURE) { + if (Tcl_ReadChars(chan, dataObj, 4096, 0) == TCL_IO_FAILURE) { + /* in case of an error reading the file */ + Tcl_DecrRefCount(dataObj); + return 0; + } + data = Tcl_GetStringFromObj(dataObj, &length); + /* should have a '' in the first 4k */ + if ((memchr(data, '>', length) == NULL) || + (MemMem(data, length, "' in the first 4k */ + testLength = (length > 4096) ? 4096 : length; + if ((memchr(data, '>', testLength) == NULL) || + (MemMem(data, testLength, " INT_MAX / 4) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("image size overflow", -1)); + Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "IMAGE_SIZE_OVERFLOW", NULL); + goto cleanRAST; + } + + imgData = (unsigned char *)attemptckalloc(wh * 4); if (imgData == NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("cannot alloc image buffer", -1)); Tcl_SetErrorCode(interp, "TK", "IMAGE", "SVG", "OUT_OF_MEMORY", NULL); goto cleanRAST; } @@ -692,11 +762,11 @@ NSVGcache *cachePtr = GetCachePtr(interp); if (cachePtr != NULL) { cachePtr->dataOrChan = dataOrChan; if (formatObj != NULL) { - data = TkGetStringFromObj(formatObj, &length); + data = Tcl_GetStringFromObj(formatObj, &length); Tcl_DStringAppend(&cachePtr->formatString, data, length); } cachePtr->nsvgImage = nsvgImage; cachePtr->ropts = *ropts; return 1; @@ -733,11 +803,11 @@ NSVGimage *nsvgImage = NULL; if ((cachePtr != NULL) && (cachePtr->nsvgImage != NULL) && (cachePtr->dataOrChan == dataOrChan)) { if (formatObj != NULL) { - data = TkGetStringFromObj(formatObj, &length); + data = Tcl_GetStringFromObj(formatObj, &length); if (strcmp(data, Tcl_DStringValue(&cachePtr->formatString)) == 0) { nsvgImage = cachePtr->nsvgImage; *ropts = cachePtr->ropts; cachePtr->nsvgImage = NULL; } Index: generic/tkImgUtil.c ================================================================== --- generic/tkImgUtil.c +++ generic/tkImgUtil.c @@ -1,11 +1,11 @@ /* * tkImgUtil.c -- * * This file contains image related utility functions. * - * Copyright (c) 1995 Sun Microsystems, Inc. + * Copyright © 1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkInt.decls ================================================================== --- generic/tkInt.decls +++ generic/tkInt.decls @@ -2,12 +2,12 @@ # # This file contains the declarations for all unsupported functions that # are exported by the Tk library. This file is used to generate the # tkIntDecls.h, tkIntPlatDecls.h, tkIntStub.c, and tkPlatStub.c files. # -# Copyright (c) 1998-1999 by Scriptics Corporation. -# Copyright (c) 2007 Daniel A. Steffen +# Copyright © 1998-1999 Scriptics Corporation. +# Copyright © 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. library tk Index: generic/tkInt.h ================================================================== --- generic/tkInt.h +++ generic/tkInt.h @@ -4,11 +4,11 @@ * Declarations for things used internally by the Tk functions but not * exported outside the module. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998 by Scriptics Corporation. + * Copyright (c) 1998 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -121,19 +121,36 @@ # define UINT2PTR(p) ((void*)(p)) # define PTR2UINT(p) ((unsigned long)(p)) # endif #endif +/* + * Fallback in case Tk is linked against a Tcl version not having TIP #585 + * (TCL_INDEX_TEMP_TABLE flag). This allows to use the internal + * INDEX_TEMP_TABLE flag of Tcl. However this is rather ugly and not robust + * since nothing prevents Tcl from changing the value of its internal flags! + */ + +#if !defined(TCL_INDEX_TEMP_TABLE) +# define TCL_INDEX_TEMP_TABLE 2 +#endif + #ifndef TCL_Z_MODIFIER # if defined(_WIN64) # define TCL_Z_MODIFIER "I" # elif defined(__GNUC__) && !defined(_WIN32) # define TCL_Z_MODIFIER "z" # else # define TCL_Z_MODIFIER "" # endif #endif /* !TCL_Z_MODIFIER */ +#undef TCL_LL_MODIFIER +#if defined(_WIN32) && (!defined(__USE_MINGW_ANSI_STDIO) || !__USE_MINGW_ANSI_STDIO) +# define TCL_LL_MODIFIER "I64" +#else +# define TCL_LL_MODIFIER "ll" +#endif /* * Opaque type declarations: */ @@ -693,10 +710,14 @@ int alwaysShowSelection; /* This is linked to the * ::tk::AlwaysShowSelection variable. */ struct TkMainInfo *nextPtr; /* Next in list of all main windows managed by * this process. */ Tcl_HashTable busyTable; /* Information used by [tk busy] command. */ + Tcl_ObjCmdProc *tclUpdateObjProc; + /* Saved Tcl [update] command, used to restore + * Tcl's version of [update] after Tk is shut + * down */ } TkMainInfo; /* * Tk keeps the following data structure for each of it's builtin bitmaps. * This structure is only used by tkBitmap.c and other platform specific @@ -899,11 +920,11 @@ XKeyEvent keyEvent; /* The real event from X11. */ #ifdef _WIN32 char trans_chars[XMaxTransChars]; /* translated characters */ unsigned char nbytes; -#elif !defined(MAC_OSC_TK) +#elif !defined(MAC_OSX_TK) char *charValuePtr; /* A pointer to a string that holds the key's * %A substitution text (before backslash * adding), or NULL if that has not been * computed yet. If non-NULL, this string was * allocated with ckalloc(). */ @@ -928,10 +949,13 @@ #endif /* See TIP #537 */ #ifndef TCL_INDEX_NONE # define TCL_INDEX_NONE (-1) #endif +#ifndef TCL_INDEX_END +# define TCL_INDEX_END ((TkSizeT)-2) +#endif /* * The following structure is used with TkMakeEnsemble to create ensemble * commands and optionally to create sub-ensembles. */ @@ -1064,14 +1088,14 @@ * outside world: */ MODULE_SCOPE const Tk_SmoothMethod tkBezierSmoothMethod; MODULE_SCOPE Tk_ImageType tkBitmapImageType; -MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtGIF; +MODULE_SCOPE Tk_PhotoImageFormatVersion3 tkImgFmtGIF; MODULE_SCOPE void (*tkHandleEventProc) (XEvent* eventPtr); MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtDefault; -MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPNG; +MODULE_SCOPE Tk_PhotoImageFormatVersion3 tkImgFmtPNG; MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtPPM; MODULE_SCOPE Tk_PhotoImageFormat tkImgFmtSVGnano; MODULE_SCOPE TkMainInfo *tkMainWindowList; MODULE_SCOPE Tk_ImageType tkPhotoImageType; MODULE_SCOPE Tcl_HashTable tkPredefBitmapTable; @@ -1090,11 +1114,11 @@ #define PI 3.14159265358979323846 #endif #endif /* - * Support for Clang Static Analyzer + * Support for Clang Static Analyzer */ #if defined(PURIFY) && defined(__clang__) #if __has_feature(attribute_analyzer_noreturn) && \ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED) @@ -1251,13 +1275,10 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData, Tcl_Interp *interp,int objc, Tcl_Obj *const objv[]); -MODULE_SCOPE int Tk_SendObjCmd(ClientData clientData, - Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_SpinboxObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int Tk_TextObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, @@ -1369,11 +1390,18 @@ MODULE_SCOPE void TkRotatePoint(double originX, double originY, double sine, double cosine, double *xPtr, double *yPtr); MODULE_SCOPE int TkGetIntForIndex(Tcl_Obj *, TkSizeT, int lastOK, TkSizeT*); -#define TkNewIndexObj(value) Tcl_NewWideIntObj((Tcl_WideInt)(value + 1) - 1) +#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) +# define TkNewIndexObj(value) Tcl_NewWideIntObj((Tcl_WideInt)(value + 1) - 1) +# define TK_OPTION_UNDERLINE_DEF(type, field) "-1", TCL_INDEX_NONE, offsetof(type, field), 0, NULL +#else +# define TkNewIndexObj(value) (((TkSizeT)(value) == TCL_INDEX_NONE) ? Tcl_NewObj() : Tcl_NewWideIntObj(value)) +# define TK_OPTION_UNDERLINE_DEF(type, field) NULL, TCL_INDEX_NONE, offsetof(type, field), TK_OPTION_NULL_OK, NULL +#endif + #ifdef _WIN32 #define TkParseColor XParseColor #else MODULE_SCOPE Status TkParseColor (Display * display, @@ -1408,29 +1436,21 @@ #if !defined(__cplusplus) && !defined(c_plusplus) # define c_class class #endif -#if TCL_UTF_MAX > 4 +/* Tcl 8.6 has a different definition of Tcl_UniChar than other Tcl versions for TCL_UTF_MAX > 3 */ +#if TCL_UTF_MAX > (3 + (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 6)) # define TkUtfToUniChar(src, ch) (size_t)(((int (*)(const char *, int *))Tcl_UtfToUniChar)(src, ch)) # define TkUniCharToUtf(ch, src) (size_t)(((int (*)(int, char *))Tcl_UniCharToUtf)(ch, src)) -# define TkUtfPrev Tcl_UtfPrev #else MODULE_SCOPE size_t TkUtfToUniChar(const char *, int *); MODULE_SCOPE size_t TkUniCharToUtf(int, char *); - MODULE_SCOPE const char *TkUtfPrev(const char *, const char *); #endif -#if TCL_MAJOR_VERSION > 8 -#define TkGetStringFromObj(objPtr, lenPtr) \ - (((objPtr)->bytes ? 0 : Tcl_GetString(objPtr)), \ - *(lenPtr) = (objPtr)->length, (objPtr)->bytes) -MODULE_SCOPE unsigned char *TkGetByteArrayFromObj(Tcl_Obj *objPtr, - size_t *lengthPtr); -#else -#define TkGetStringFromObj Tcl_GetStringFromObj -#define TkGetByteArrayFromObj Tcl_GetByteArrayFromObj +#if defined(_WIN32) && !defined(STATIC_BUILD) && TCL_MAJOR_VERSION < 9 +# define tcl_CreateFileHandler reserved9 #endif /* * Unsupported commands. */ Index: generic/tkIntDecls.h ================================================================== --- generic/tkIntDecls.h +++ generic/tkIntDecls.h @@ -4,11 +4,11 @@ * This file contains the declarations for all unsupported * functions that are exported by the Tk library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkIntPlatDecls.h ================================================================== --- generic/tkIntPlatDecls.h +++ generic/tkIntPlatDecls.h @@ -4,11 +4,11 @@ * This file contains the declarations for all platform dependent * unsupported functions that are exported by the Tk library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998-1999 Scriptics Corporation. * All rights reserved. */ #ifndef _TKINTPLATDECLS #define _TKINTPLATDECLS Index: generic/tkIntXlibDecls.h ================================================================== --- generic/tkIntXlibDecls.h +++ generic/tkIntXlibDecls.h @@ -4,11 +4,11 @@ * This file contains the declarations for all platform dependent * unsupported functions that are exported by the Tk library. These * interfaces are not guaranteed to remain the same between * versions. Use at your own risk. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998-1999 Scriptics Corporation. * All rights reserved. */ #ifndef _TKINTXLIBDECLS #define _TKINTXLIBDECLS Index: generic/tkListbox.c ================================================================== --- generic/tkListbox.c +++ generic/tkListbox.c @@ -3,12 +3,12 @@ * * This module implements listbox widgets for the Tk toolkit. A listbox * displays a collection of strings, one per line, and provides scrolling * and selection. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1114,11 +1114,11 @@ result = Tcl_ListObjIndex(interp, listPtr->listObj, index, &el); if (result != TCL_OK) { return result; } - stringRep = TkGetStringFromObj(el, &stringLen); + stringRep = Tcl_GetStringFromObj(el, &stringLen); Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); if (listPtr->justify == TK_JUSTIFY_LEFT) { x = (listPtr->inset + listPtr->selBorderWidth) - listPtr->xOffset; @@ -2077,11 +2077,11 @@ /* * Draw the actual text of this item. */ Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); - stringRep = TkGetStringFromObj(curElement, &stringLen); + stringRep = Tcl_GetStringFromObj(curElement, &stringLen); textWidth = Tk_TextWidth(listPtr->tkfont, stringRep, stringLen); Tk_GetFontMetrics(listPtr->tkfont, &fm); y += fm.ascent + listPtr->selBorderWidth; @@ -2261,11 +2261,11 @@ result = Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); if (result != TCL_OK) { continue; } - text = TkGetStringFromObj(element, &textLength); + text = Tcl_GetStringFromObj(element, &textLength); Tk_GetFontMetrics(listPtr->tkfont, &fm); pixelWidth = Tk_TextWidth(listPtr->tkfont, text, textLength); if (pixelWidth > listPtr->maxWidth) { listPtr->maxWidth = pixelWidth; } @@ -2339,11 +2339,11 @@ /* * Check if any of the new elements are wider than the current widest; * if so, update our notion of "widest." */ - stringRep = TkGetStringFromObj(objv[i], &length); + stringRep = Tcl_GetStringFromObj(objv[i], &length); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length); if (pixelWidth > listPtr->maxWidth) { listPtr->maxWidth = pixelWidth; } } @@ -2498,11 +2498,11 @@ * element to disappear for us to have to recompute the width. */ if (widthChanged == 0) { Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &element); - stringRep = TkGetStringFromObj(element, &length); + stringRep = Tcl_GetStringFromObj(element, &length); pixelWidth = Tk_TextWidth(listPtr->tkfont, stringRep, length); if (pixelWidth == listPtr->maxWidth) { widthChanged = 1; } } @@ -2802,11 +2802,11 @@ */ badIndex: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad listbox index \"%s\": must be active, anchor, end, @x,y," - " or a number", Tcl_GetString(indexObj))); + " or an index", Tcl_GetString(indexObj))); Tcl_SetErrorCode(interp, "TK", "VALUE", "LISTBOX_INDEX", NULL); return TCL_ERROR; } /* @@ -3146,11 +3146,11 @@ if (needNewline) { Tcl_DStringAppend(&selection, "\n", 1); } Tcl_ListObjIndex(listPtr->interp, listPtr->listObj, i, &curElement); - stringRep = TkGetStringFromObj(curElement, &stringLen); + stringRep = Tcl_GetStringFromObj(curElement, &stringLen); Tcl_DStringAppend(&selection, stringRep, stringLen); needNewline = 1; } } Index: generic/tkMacWinMenu.c ================================================================== --- generic/tkMacWinMenu.c +++ generic/tkMacWinMenu.c @@ -2,11 +2,11 @@ * tkMacWinMenu.c -- * * This module implements the common elements of the Mac and Windows * specific features of menus. This file is not used for UNIX. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkMain.c ================================================================== --- generic/tkMain.c +++ generic/tkMain.c @@ -98,11 +98,11 @@ * always claim to be running on a tty. This probably isn't the right way * to do it. */ #if !defined(STATIC_BUILD) - if (tclStubsPtr->reserved9 && tclIntPlatStubsPtr->tclpIsAtty) { + if (tclStubsPtr->tcl_CreateFileHandler && tclIntPlatStubsPtr->tclpIsAtty) { /* We are running on Cygwin */ return tclIntPlatStubsPtr->tclpIsAtty(fd); } #endif handle = GetStdHandle(STD_INPUT_HANDLE + fd); @@ -187,11 +187,11 @@ } } #if defined(_WIN32) && !defined(UNICODE) && !defined(STATIC_BUILD) - if (tclStubsPtr->reserved9) { + if (tclStubsPtr->tcl_CreateFileHandler) { /* We are running win32 Tk under Cygwin, so let's check * whether the env("DISPLAY") variable or the -display * argument is set. If so, we really want to run the * Tk_MainEx function of libtk8.?.dll, not this one. */ if (Tcl_GetVar2(interp, "env", "DISPLAY", TCL_GLOBAL_ONLY)) { @@ -219,11 +219,11 @@ Tcl_Preserve(interp); #if defined(_WIN32) #if !defined(STATIC_BUILD) /* If compiled for Win32 but running on Cygwin, don't use console */ - if (!tclStubsPtr->reserved9) + if (!tclStubsPtr->tcl_CreateFileHandler) #endif Tk_InitConsoleChannels(interp); #endif #ifdef MAC_OSX_TK @@ -409,12 +409,18 @@ int code; TkSizeT count; InteractiveState *isPtr = (InteractiveState *)clientData; Tcl_Channel chan = isPtr->input; Tcl_Interp *interp = isPtr->interp; + Tcl_DString savedEncoding; + Tcl_DStringInit(&savedEncoding); + Tcl_GetChannelOption(NULL, chan, "-encoding", &savedEncoding); + Tcl_SetChannelOption(NULL, chan, "-encoding", "utf-8"); count = Tcl_Gets(chan, &isPtr->line); + Tcl_SetChannelOption(NULL, chan, "-encoding", Tcl_DStringValue(&savedEncoding)); + Tcl_DStringFree(&savedEncoding); if ((count == TCL_IO_FAILURE) && !isPtr->gotPartial) { if (isPtr->tty) { Tcl_Exit(0); } else { Index: generic/tkMenu.c ================================================================== --- generic/tkMenu.c +++ generic/tkMenu.c @@ -4,12 +4,12 @@ * This file contains most of the code for implementing menus in Tk. It takes * care of all of the generic (platform-independent) parts of menus, and is * supplemented by platform-specific files. The geometry calculation and * drawing code for menus is in the file tkMenuDraw.c * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -158,12 +158,12 @@ offsetof(TkMenuEntry, labelPtr), TCL_INDEX_NONE, 0, NULL, 0}, {TK_OPTION_STRING_TABLE, "-state", NULL, NULL, DEF_MENU_ENTRY_STATE, TCL_INDEX_NONE, offsetof(TkMenuEntry, state), 0, (ClientData) menuStateStrings, 0}, - {TK_OPTION_INT, "-underline", NULL, NULL, - DEF_MENU_ENTRY_UNDERLINE, TCL_INDEX_NONE, offsetof(TkMenuEntry, underline), 0, NULL, 0}, + {TK_OPTION_INDEX, "-underline", NULL, NULL, + TK_OPTION_UNDERLINE_DEF(TkMenuEntry, underline), 0}, {TK_OPTION_END, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0} }; static const Tk_OptionSpec tkSeparatorEntryConfigSpecs[] = { {TK_OPTION_BORDER, "-background", NULL, NULL, @@ -841,13 +841,15 @@ goto error; } if (GetMenuIndex(interp, menuPtr, objv[2], 0, &index) != TCL_OK) { goto error; } +#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) if (index == TCL_INDEX_NONE) { - Tcl_SetObjResult(interp, Tcl_NewStringObj("none", -1)); + Tcl_SetObjResult(interp, Tcl_NewObj()); } else +#endif Tcl_SetObjResult(interp, TkNewIndexObj(index)); break; } case MENU_INSERT: if (objc < 4) { @@ -1708,16 +1710,16 @@ */ if (mePtr->labelPtr == NULL) { mePtr->labelLength = 0; } else { - (void)TkGetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); + (void)Tcl_GetStringFromObj(mePtr->labelPtr, &mePtr->labelLength); } if (mePtr->accelPtr == NULL) { mePtr->accelLength = 0; } else { - (void)TkGetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); + (void)Tcl_GetStringFromObj(mePtr->accelPtr, &mePtr->accelLength); } /* * If this is a cascade entry, the platform-specific data of the child * menu has to be updated. Also, the links that point to parents and @@ -2126,11 +2128,11 @@ const char *string; if (TkGetIntForIndex(objPtr, menuPtr->numEntries - 1, lastOK, indexPtr) == TCL_OK) { /* TCL_INDEX_NONE is only accepted if it does not result from a negative number */ if (*indexPtr != TCL_INDEX_NONE || Tcl_GetString(objPtr)[0] != '-') { - if (*indexPtr >= menuPtr->numEntries) { + if (*indexPtr + 1 >= menuPtr->numEntries + 1) { *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1); } return TCL_OK; } } @@ -2145,14 +2147,20 @@ if ((string[0] == 'l') && (strcmp(string, "last") == 0)) { *indexPtr = menuPtr->numEntries - ((lastOK) ? 0 : 1); goto success; } + if (string[0] == 0) { + *indexPtr = TCL_INDEX_NONE; + goto success; + } +#if !defined(TK_NO_DEPRECATED) && TK_MAJOR_VERSION < 9 if ((string[0] == 'n') && (strcmp(string, "none") == 0)) { *indexPtr = TCL_INDEX_NONE; goto success; } +#endif if (string[0] == '@') { if (GetIndexFromCoords(NULL, menuPtr, string, indexPtr) == TCL_OK) { goto success; @@ -2274,11 +2282,11 @@ mePtr->type = type; mePtr->optionTable = tsdPtr->entryOptionTables[type]; mePtr->menuPtr = menuPtr; mePtr->labelPtr = NULL; mePtr->labelLength = 0; - mePtr->underline = -1; + mePtr->underline = INT_MIN; mePtr->bitmapPtr = NULL; mePtr->imagePtr = NULL; mePtr->image = NULL; mePtr->selectImagePtr = NULL; mePtr->selectImage = NULL; Index: generic/tkMenu.h ================================================================== --- generic/tkMenu.h +++ generic/tkMenu.h @@ -2,11 +2,11 @@ * tkMenu.h -- * * Declarations shared among all of the files that implement menu * widgets. * - * Copyright (c) 1996-1998 by Sun Microsystems, Inc. + * Copyright © 1996-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkMenuDraw.c ================================================================== --- generic/tkMenuDraw.c +++ generic/tkMenuDraw.c @@ -2,11 +2,11 @@ * tkMenuDraw.c -- * * This module implements the platform-independent drawing and geometry * calculations of menu widgets. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkMenubutton.c ================================================================== --- generic/tkMenubutton.c +++ generic/tkMenubutton.c @@ -2,12 +2,12 @@ * tkMenubutton.c -- * * This module implements button-like widgets that are used to invoke * pull-down menus. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -142,13 +142,12 @@ {TK_OPTION_STRING, "-text", "text", "Text", DEF_MENUBUTTON_TEXT, TCL_INDEX_NONE, offsetof(TkMenuButton, text), 0, 0, 0}, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", DEF_MENUBUTTON_TEXT_VARIABLE, TCL_INDEX_NONE, offsetof(TkMenuButton, textVarName), TK_OPTION_NULL_OK, 0, 0}, - {TK_OPTION_INT, "-underline", "underline", "Underline", - DEF_MENUBUTTON_UNDERLINE, TCL_INDEX_NONE, offsetof(TkMenuButton, underline), - 0, 0, 0}, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(TkMenuButton, underline), 0}, {TK_OPTION_STRING, "-width", "width", "Width", DEF_MENUBUTTON_WIDTH, TCL_INDEX_NONE, offsetof(TkMenuButton, widthString), 0, 0, 0}, {TK_OPTION_PIXELS, "-wraplength", "wrapLength", "WrapLength", DEF_MENUBUTTON_WRAP_LENGTH, TCL_INDEX_NONE, offsetof(TkMenuButton, wrapLength), @@ -259,11 +258,11 @@ Tk_PathName(mbPtr->tkwin), MenuButtonWidgetObjCmd, mbPtr, MenuButtonCmdDeletedProc); mbPtr->optionTable = optionTable; mbPtr->menuName = NULL; mbPtr->text = NULL; - mbPtr->underline = -1; + mbPtr->underline = INT_MIN; mbPtr->textVarName = NULL; mbPtr->bitmap = None; mbPtr->imageString = NULL; mbPtr->image = NULL; mbPtr->state = STATE_NORMAL; Index: generic/tkMenubutton.h ================================================================== --- generic/tkMenubutton.h +++ generic/tkMenubutton.h @@ -2,11 +2,11 @@ * tkMenubutton.h -- * * Declarations of types and functions used to implement the menubutton * widget. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright © 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -62,11 +62,11 @@ * Information about what's displayed in the menu button: */ char *text; /* Text to display in button (malloc'ed) or * NULL. */ - int underline; /* Index of character to underline. */ + int underline; /* Index of character to underline. INT_MIN means no underline */ char *textVarName; /* Name of variable (malloc'ed) or NULL. If * non-NULL, button displays the contents of * this variable. */ Pixmap bitmap; /* Bitmap to display or None. If not None then * text and textVar and underline are Index: generic/tkMessage.c ================================================================== --- generic/tkMessage.c +++ generic/tkMessage.c @@ -3,13 +3,13 @@ * * This module implements a message widgets for the Tk toolkit. A message * widget displays a multi-line string in a window according to a * particular aspect ratio. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 by Ajuba Solutions. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Ajuba Solutions. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkObj.c ================================================================== --- generic/tkObj.c +++ generic/tkObj.c @@ -1,11 +1,11 @@ /* * tkObj.c -- * * This file contains functions that implement the common Tk object types * - * Copyright (c) 1997 Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -48,11 +48,10 @@ */ typedef struct { const Tcl_ObjType *doubleTypePtr; const Tcl_ObjType *intTypePtr; - const Tcl_ObjType *endTypePtr; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* * The following structure is the internal representation for mm objects. @@ -97,10 +96,13 @@ static int SetMMFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetPixelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int SetWindowFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); #if TCL_MAJOR_VERSION < 9 +#ifdef __cplusplus +extern "C" { +#endif #if defined(USE_TCL_STUBS) /* Little hack to eliminate the need for "tclInt.h" here: Just copy a small portion of TclIntStubs, just enough to make it work */ typedef struct TclIntStubs { @@ -107,19 +109,22 @@ int magic; void *hooks; void (*dummy[34]) (void); /* dummy entries 0-33, not used */ int (*tclGetIntForIndex) (Tcl_Interp *interp, Tcl_Obj *objPtr, int endValue, int *indexPtr); /* 34 */ } TclIntStubs; -extern const struct TclIntStubs *tclIntStubsPtr; +extern const TclIntStubs *tclIntStubsPtr; # undef Tcl_GetIntForIndex # define Tcl_GetIntForIndex(interp, obj, max, ptr) ((tclIntStubsPtr->tclGetIntForIndex == NULL)? \ ((int (*)(Tcl_Interp*, Tcl_Obj *, int, int*))(void *)((&(tclStubsPtr->tcl_PkgProvideEx))[645]))((interp), (obj), (max), (ptr)): \ tclIntStubsPtr->tclGetIntForIndex((interp), (obj), (max), (ptr))) #elif TCL_MINOR_VERSION < 7 extern int TclGetIntForIndex(Tcl_Interp*, Tcl_Obj *, int, int*); # define Tcl_GetIntForIndex(interp, obj, max, ptr) TclGetIntForIndex(interp, obj, max, ptr) +#endif +#ifdef __cplusplus +} #endif #endif /* * The following structure defines the implementation of the "pixel" Tcl @@ -182,15 +187,10 @@ if (tsdPtr->doubleTypePtr == NULL) { /* Smart initialization of doubleTypePtr/intTypePtr without * hash-table lookup or creating complete Tcl_Obj's */ Tcl_Obj obj; - obj.bytes = (char *)"end"; - obj.length = 3; - obj.typePtr = NULL; - Tcl_GetIntForIndex(NULL, &obj, TCL_INDEX_NONE, (TkSizeT *)&obj.internalRep.doubleValue); - tsdPtr->endTypePtr = obj.typePtr; obj.bytes = (char *)"0.0"; obj.length = 3; obj.typePtr = NULL; Tcl_GetDoubleFromObj(NULL, &obj, &obj.internalRep.doubleValue); tsdPtr->doubleTypePtr = obj.typePtr; @@ -206,13 +206,12 @@ /* *---------------------------------------------------------------------- * * TkGetIntForIndex -- * - * Almost the same as Tcl_GetIntForIndex, but it return an int, and it is - * more restricted. For example it only accepts "end", not "end-1", and - * only "2", not "1+1" + * Almost the same as Tcl_GetIntForIndex, but it return an int. Accepts + * "" (empty string) as well. * * Results: * The return value is a standard Tcl object result. * * Side effects: @@ -226,28 +225,26 @@ Tcl_Obj *indexObj, TkSizeT end, int lastOK, TkSizeT *indexPtr) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - + if (indexObj == NULL) { + *indexPtr = TCL_INDEX_NONE; + return TCL_OK; + } if (Tcl_GetIntForIndex(NULL, indexObj, end + lastOK, indexPtr) != TCL_OK) { - return TCL_ERROR; - } - if (indexObj->typePtr == tsdPtr->endTypePtr) { - /* check for "end", but not "end-??" or "end+??" */ - return (*indexPtr == (end + lastOK)) ? TCL_OK : TCL_ERROR; - } - if (indexObj->typePtr != tsdPtr->intTypePtr) { - /* Neither do we accept "??-??" or "??+??" */ + const char *value = Tcl_GetString(indexObj); + if (!*value) { + *indexPtr = TCL_INDEX_NONE; + return TCL_OK; + } return TCL_ERROR; } #if TCL_MAJOR_VERSION < 9 - if ((*indexPtr < -1) || (end < -1)) { - return TCL_ERROR; - } + if (*indexPtr < -1) { + *indexPtr = TCL_INDEX_NONE; + } else if (end >= -1) #endif if ((*indexPtr + 1) > (end + 1)) { *indexPtr = end + 1; } return TCL_OK; Index: generic/tkOldConfig.c ================================================================== --- generic/tkOldConfig.c +++ generic/tkOldConfig.c @@ -3,12 +3,12 @@ * * This file contains the Tk_ConfigureWidget function. THIS FILE IS HERE * FOR BACKWARD COMPATIBILITY; THE NEW CONFIGURATION PACKAGE SHOULD BE * USED FOR NEW PROJECTS. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkOldTest.c ================================================================== --- generic/tkOldTest.c +++ generic/tkOldTest.c @@ -4,13 +4,13 @@ * This file contains C command functions for additional Tcl * commands that are used to test Tk's support for legacy * interfaces. These commands are not normally included in Tcl/Tk * applications; they're only used for testing. * - * Copyright (c) 1993-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1993-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * Contributions by Don Porter, NIST, 2007. (not subject to US copyright) * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkOption.c ================================================================== --- generic/tkOption.c +++ generic/tkOption.c @@ -3,12 +3,12 @@ * * This module contains functions to manage the option database, which * allows various strings to be associated with windows either by name or * by class or both. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkPack.c ================================================================== --- generic/tkPack.c +++ generic/tkPack.c @@ -2,12 +2,12 @@ * tkPack.c -- * * This file contains code to implement the "packer" geometry manager for * Tk. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1179,11 +1179,11 @@ packPtr->flags &= ~(FILLX|FILLY|EXPAND); packPtr->flags |= OLD_STYLE; for (index = 0 ; index < optionCount; index++) { Tcl_Obj *curOptPtr = options[index]; TkSizeT length; - const char *curOpt = TkGetStringFromObj(curOptPtr, &length); + const char *curOpt = Tcl_GetStringFromObj(curOptPtr, &length); c = curOpt[0]; if ((c == 't') && (strncmp(curOpt, "top", length)) == 0) { Index: generic/tkPanedWindow.c ================================================================== --- generic/tkPanedWindow.c +++ generic/tkPanedWindow.c @@ -4,12 +4,12 @@ * This module implements "paned window" widgets that are object based. A * "paned window" is a widget that manages the geometry for some number * of other widgets, placing a movable "sash" between them, which can be * used to alter the relative sizes of adjacent widgets. * - * Copyright (c) 1997 Sun Microsystems, Inc. - * Copyright (c) 2000 Ajuba Solutions. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 2000 Ajuba Solutions. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkPkgConfig.c ================================================================== --- generic/tkPkgConfig.c +++ generic/tkPkgConfig.c @@ -2,12 +2,12 @@ * tkPkgConfig.c -- * * This file contains the configuration information to embed into the tcl * binary library. * - * Copyright (c) 2002 Andreas Kupries - * Copyright (c) 2017 Stuart Cassoff + * Copyright © 2002 Andreas Kupries + * Copyright © 2017 Stuart Cassoff * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -124,10 +124,13 @@ {"docdir,runtime", CFG_RUNTIME_DOCDIR}, #endif #ifdef CFG_RUNTIME_DEMODIR {"demodir,runtime", CFG_RUNTIME_DEMODIR}, #endif +#if !defined(STATIC_BUILD) + {"dllfile,runtime", CFG_RUNTIME_DLLFILE}, +#endif /* Installation paths to various stuff */ #ifdef CFG_INSTALL_LIBDIR {"libdir,install", CFG_INSTALL_LIBDIR}, Index: generic/tkPlace.c ================================================================== --- generic/tkPlace.c +++ generic/tkPlace.c @@ -2,12 +2,12 @@ * tkPlace.c -- * * This file contains code to implement a simple geometry manager for Tk * based on absolute placement or "rubber-sheet" placement. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkPlatDecls.h ================================================================== --- generic/tkPlatDecls.h +++ generic/tkPlatDecls.h @@ -1,11 +1,11 @@ /* * tkPlatDecls.h -- * * Declarations of functions in the platform-specific public Tcl API. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright (c) 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkPointer.c ================================================================== --- generic/tkPointer.c +++ generic/tkPointer.c @@ -4,11 +4,11 @@ * This file contains functions for emulating the X server pointer and * grab state machine. This file is used by the Mac and Windows platforms * to generate appropriate enter/leave events, and to update the global * grab window information. * - * Copyright (c) 1996 by Sun Microsystems, Inc. + * Copyright © 1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -500,11 +500,11 @@ { ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr == tsdPtr->lastWinPtr) { - tsdPtr->lastWinPtr = NULL; + tsdPtr->lastWinPtr = TkGetContainer(winPtr); } if (winPtr == tsdPtr->grabWinPtr) { tsdPtr->grabWinPtr = NULL; } if (winPtr == tsdPtr->restrictWinPtr) { Index: generic/tkRectOval.c ================================================================== --- generic/tkRectOval.c +++ generic/tkRectOval.c @@ -1,12 +1,12 @@ /* * tkRectOval.c -- * * This file implements rectangle and oval items for canvas widgets. * - * Copyright (c) 1991-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1991-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkScale.c ================================================================== --- generic/tkScale.c +++ generic/tkScale.c @@ -7,13 +7,13 @@ * * The modifications to use floating-point values are based on an * implementation by Paul Mackerras. The -variable option is due to * Henning Schulzrinne. All of these are used with permission. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-2000 by Scriptics Corporation. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkScale.h ================================================================== --- generic/tkScale.h +++ generic/tkScale.h @@ -2,12 +2,12 @@ * tkScale.h -- * * Declarations of types and functions used to implement the scale * widget. * - * Copyright (c) 1996 by Sun Microsystems, Inc. - * Copyright (c) 1999-2000 by Scriptics Corporation. + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 1999-2000 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkScrollbar.c ================================================================== --- generic/tkScrollbar.c +++ generic/tkScrollbar.c @@ -3,12 +3,12 @@ * * This module implements a scrollbar widgets for the Tk toolkit. A * scrollbar displays a slider and two arrows; mouse clicks on features * within the scrollbar cause scrolling commands to be invoked. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -269,11 +269,11 @@ } if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "activate element"); goto error; } - c = TkGetStringFromObj(objv[2], &len)[0]; + c = Tcl_GetStringFromObj(objv[2], &len)[0]; oldActiveField = scrollPtr->activeField; if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow1") == 0)) { scrollPtr->activeField = TOP_ARROW; } else if ((c == 'a') && (strcmp(Tcl_GetString(objv[2]), "arrow2") == 0)) { scrollPtr->activeField = BOTTOM_ARROW; Index: generic/tkScrollbar.h ================================================================== --- generic/tkScrollbar.h +++ generic/tkScrollbar.h @@ -2,11 +2,11 @@ * tkScrollbar.h -- * * Declarations of types and functions used to implement the scrollbar * widget. * - * Copyright (c) 1996 by Sun Microsystems, Inc. + * Copyright © 1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkSelect.c ================================================================== --- generic/tkSelect.c +++ generic/tkSelect.c @@ -2,12 +2,12 @@ * tkSelect.c -- * * This file manages the selection for the Tk toolkit, translating * between the standard X ICCCM conventions and Tcl commands. * - * Copyright (c) 1990-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -898,11 +898,11 @@ } else if (formatName != NULL) { format = Tk_InternAtom(tkwin, formatName); } else { format = XA_STRING; } - string = TkGetStringFromObj(objs[1], &cmdLength); + string = Tcl_GetStringFromObj(objs[1], &cmdLength); if (cmdLength == 0) { Tk_DeleteSelHandler(tkwin, selection, target); } else { cmdInfoPtr = (CommandInfo *)ckalloc(offsetof(CommandInfo, command) + 1 + cmdLength); @@ -1189,11 +1189,11 @@ /* * Using UTF8_STRING instead of the XA_UTF8_STRING macro allows us to * support older X servers that didn't have UTF8_STRING yet. This is * necessary on Unix systems. For more information, see: - * http://www.cl.cam.ac.uk/~mgk25/unicode.html#x11 + * https://www.cl.cam.ac.uk/~mgk25/unicode.html#x11 */ #if !defined(_WIN32) dispPtr->utf8Atom = Tk_InternAtom(tkwin, "UTF8_STRING"); #else @@ -1397,16 +1397,16 @@ if (cmdInfoPtr->interp != NULL) { if (length <= (int)maxBytes) { cmdInfoPtr->charOffset += Tcl_NumUtfChars(string, -1); cmdInfoPtr->buffer[0] = '\0'; } else { - int ch; + Tcl_UniChar ch = 0; p = string; string += count; numChars = 0; while (p < string) { - p += TkUtfToUniChar(p, &ch); + p += Tcl_UtfToUniChar(p, &ch); numChars++; } cmdInfoPtr->charOffset += numChars; length = p - string; if (length > 0) { Index: generic/tkSelect.h ================================================================== --- generic/tkSelect.h +++ generic/tkSelect.h @@ -2,11 +2,11 @@ * tkSelect.h -- * * Declarations of types shared among the files that implement selection * support. * - * Copyright (c) 1995 Sun Microsystems, Inc. + * Copyright © 1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkSquare.c ================================================================== --- generic/tkSquare.c +++ generic/tkSquare.c @@ -5,11 +5,11 @@ * "square" is a widget that displays a single square that can be moved * around and resized. This file is intended as an example of how to * build a widget; it isn't included in the normal wish, but it is * included in "tktest". * - * Copyright (c) 1997 Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkStubInit.c ================================================================== --- generic/tkStubInit.c +++ generic/tkStubInit.c @@ -1,11 +1,11 @@ /* * tkStubInit.c -- * * This file contains the initializers for the Tk stub vectors. * - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1330,10 +1330,11 @@ Tk_GetButtonMask, /* 275 */ Tk_GetDoublePixelsFromObj, /* 276 */ Tk_NewWindowObj, /* 277 */ Tk_SendVirtualEvent, /* 278 */ Tk_FontGetDescription, /* 279 */ + Tk_CreatePhotoImageFormatVersion3 /* 280 */ }; /* !END!: Do not edit above this line. */ Index: generic/tkStubLib.c ================================================================== --- generic/tkStubLib.c +++ generic/tkStubLib.c @@ -2,12 +2,12 @@ * tkStubLib.c -- * * Stub object that will be statically linked into extensions that want * to access Tk. * - * Copyright (c) 1998-1999 by Scriptics Corporation. - * Copyright (c) 1998 Paul Duffin. + * Copyright © 1998-1999 Scriptics Corporation. + * Copyright © 1998 Paul Duffin. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -73,19 +73,23 @@ Tk_InitStubs( Tcl_Interp *interp, const char *version, int exact) { - const char *packageName = "Tk"; + const char *packageName = "tk"; const char *errMsg = NULL; void *clientData = NULL; const char *actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, packageName, version, 0, &clientData); - const TkStubs *stubsPtr = (const TkStubs *)clientData; if (actualVersion == NULL) { - return NULL; + packageName = "Tk"; + actualVersion = tclStubsPtr->tcl_PkgRequireEx(interp, + packageName, version, 0, &clientData); + if (actualVersion == NULL) { + return NULL; + } } if (exact) { const char *p = version; int count = 0; @@ -111,19 +115,19 @@ if (actualVersion == NULL) { return NULL; } } } - if (stubsPtr == NULL) { + if (clientData == NULL) { errMsg = "missing stub table pointer"; } else { - tkStubsPtr = stubsPtr; - if (stubsPtr->hooks) { - tkPlatStubsPtr = stubsPtr->hooks->tkPlatStubs; - tkIntStubsPtr = stubsPtr->hooks->tkIntStubs; - tkIntPlatStubsPtr = stubsPtr->hooks->tkIntPlatStubs; - tkIntXlibStubsPtr = stubsPtr->hooks->tkIntXlibStubs; + tkStubsPtr = (const TkStubs *)clientData; + if (tkStubsPtr->hooks) { + tkPlatStubsPtr = tkStubsPtr->hooks->tkPlatStubs; + tkIntStubsPtr = tkStubsPtr->hooks->tkIntStubs; + tkIntPlatStubsPtr = tkStubsPtr->hooks->tkIntPlatStubs; + tkIntXlibStubsPtr = tkStubsPtr->hooks->tkIntXlibStubs; } else { tkPlatStubsPtr = NULL; tkIntStubsPtr = NULL; tkIntPlatStubsPtr = NULL; tkIntXlibStubsPtr = NULL; Index: generic/tkStyle.c ================================================================== --- generic/tkStyle.c +++ generic/tkStyle.c @@ -1,12 +1,12 @@ /* * tkStyle.c -- * * This file implements the widget styles and themes support. * - * Copyright (c) 1990-1993 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1990-1993 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkTest.c ================================================================== --- generic/tkTest.c +++ generic/tkTest.c @@ -4,13 +4,13 @@ * This file contains C command functions for a bunch of additional Tcl * commands that are used for testing out Tcl's C interfaces. These * commands are not normally included in Tcl applications; they're only * used for testing. * - * Copyright (c) 1993-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 1998-1999 by Scriptics Corporation. + * Copyright © 1993-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 1998-1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -245,11 +245,11 @@ /* * Create additional commands for testing Tk. */ - if (Tcl_PkgProvideEx(interp, "Tktest", TK_PATCH_LEVEL, NULL) == TCL_ERROR) { + if (Tcl_PkgProvideEx(interp, "tk::test", TK_PATCH_LEVEL, NULL) == TCL_ERROR) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "square", SquareObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "testbitmap", TestbitmapObjCmd, @@ -1931,15 +1931,11 @@ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument strings. */ { char buffer[256]; Tcl_WideInt wideInt; -#ifdef _WIN32 - __int64 longLongInt; -#else long long longLongInt; -#endif (void)dummy; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "wideint"); return TCL_ERROR; @@ -1954,11 +1950,11 @@ * which still woudn't tell if the assumed size is correct: We want this * test-case to fail if the 64-bit value is printed as truncated to 32-bit. */ sprintf(buffer, "%s%s%s%s%s%s%s%s%" TCL_LL_MODIFIER "d %" TCL_LL_MODIFIER "u", "", "", "", "", "", "", "", "", - (Tcl_WideInt)longLongInt, (Tcl_WideUInt)longLongInt); + longLongInt, (unsigned long long)longLongInt); Tcl_AppendResult(interp, buffer, NULL); return TCL_OK; } #if !(defined(_WIN32) || defined(MAC_OSX_TK) || defined(__CYGWIN__)) Index: generic/tkText.c ================================================================== --- generic/tkText.c +++ generic/tkText.c @@ -4,13 +4,13 @@ * This module provides a big chunk of the implementation of multi-line * editable text widgets for Tk. Among other things, it provides the Tcl * command interfaces to text widgets. The B-tree representation of text * and its actual display are implemented elsewhere. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1996 Sun Microsystems, Inc. - * Copyright (c) 1999 by Scriptics Corporation. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1996 Sun Microsystems, Inc. + * Copyright © 1999 Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -863,11 +863,11 @@ } for (i = 2; i < objc-2; i++) { int value; TkSizeT length; - const char *option = TkGetStringFromObj(objv[i], &length); + const char *option = Tcl_GetStringFromObj(objv[i], &length); char c; if (length < 2 || option[0] != '-') { goto badOption; } @@ -1273,16 +1273,16 @@ * -displaychars (or any unique prefix). */ i = 2; if (objc > 3) { - name = TkGetStringFromObj(objv[i], &length); + name = Tcl_GetStringFromObj(objv[i], &length); if (length > 1 && name[0] == '-') { if (strncmp("-displaychars", name, length) == 0) { i++; visible = 1; - name = TkGetStringFromObj(objv[i], &length); + name = Tcl_GetStringFromObj(objv[i], &length); } if ((i < objc-1) && (length == 2) && !strcmp("--", name)) { i++; } } @@ -2634,11 +2634,11 @@ TkSizeT length; TkText *tPtr; int *lineAndByteIndex; int resetViewCount; int pixels[2*PIXEL_CLIENTS]; - const char *string = TkGetStringFromObj(stringPtr, &length); + const char *string = Tcl_GetStringFromObj(stringPtr, &length); if (sharedTextPtr == NULL) { sharedTextPtr = textPtr->sharedTextPtr; } @@ -3344,33 +3344,25 @@ TkTextMakeByteIndex(sharedTextPtr->tree, textPtr, line, byteIndex, &indexTmp); TkTextSetYView(tPtr, &indexTmp, 0); } } else { - TkTextMakeByteIndex(sharedTextPtr->tree, tPtr, line, + TkTextMakeByteIndex(sharedTextPtr->tree, NULL, line, byteIndex, &indexTmp); /* * line may be before -startline of tPtr and must be * clamped to -startline before providing it to * TkTextSetYView otherwise lines before -startline * would be displayed. * There is no need to worry about -endline however, * because the view will only be reset if the deletion - * involves the TOP line of the screen + * involves the TOP line of the screen. That said, + * the following call adjusts to both. */ - if (tPtr->start != NULL) { - int start; - TkTextIndex indexStart; - - start = TkBTreeLinesTo(NULL, tPtr->start); - TkTextMakeByteIndex(sharedTextPtr->tree, NULL, start, - 0, &indexStart); - if (TkTextIndexCmp(&indexTmp, &indexStart) < 0) { - indexTmp = indexStart; - } - } + TkTextIndexAdjustToStartEnd(tPtr, &indexTmp, 0); + TkTextSetYView(tPtr, &indexTmp, 0); } } resetViewCount += 2; } @@ -4757,11 +4749,11 @@ const char *str; if (TkTextGetObjIndex(interp, textPtr, objv[arg], &index2) != TCL_OK) { return TCL_ERROR; } - str = TkGetStringFromObj(objv[arg], &length); + str = Tcl_GetStringFromObj(objv[arg], &length); if (strncmp(str, "end", length) == 0) { atEnd = 1; } } if (TkTextIndexCmp(&index1, &index2) >= 0) { @@ -5826,11 +5818,11 @@ * We only need to set the matchLength once for exact searches, and we * do it here. It is also used below as the actual pattern length, so * it has dual purpose. */ - pattern = TkGetStringFromObj(patObj, &matchLength); + pattern = Tcl_GetStringFromObj(patObj, &matchLength); nl = strchr(pattern, '\n'); /* * If there is no newline, or it is the very end of the string, then * we don't need any special treatment, since single-line matching Index: generic/tkText.h ================================================================== --- generic/tkText.h +++ generic/tkText.h @@ -1168,10 +1168,12 @@ MODULE_SCOPE int TkTextYviewCmd(TkText *textPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE void TkTextWinFreeClient(Tcl_HashEntry *hPtr, TkTextEmbWindowClient *client); MODULE_SCOPE void TkTextRunAfterSyncCmd(ClientData clientData); +MODULE_SCOPE int TkTextIndexAdjustToStartEnd(TkText *textPtr, + TkTextIndex *indexPtr, int err); #endif /* _TKTEXT */ /* * Local Variables: * mode: c Index: generic/tkTextBTree.c ================================================================== --- generic/tkTextBTree.c +++ generic/tkTextBTree.c @@ -3,12 +3,12 @@ * * This file contains code that manages the B-tree representation of text * for Tk's text widget and implements character and toggle segment * types. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1995 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1995 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1725,10 +1725,30 @@ if (linePtr == NULL) { Tcl_Panic("TkBTreeFindPixelLine ran out of lines"); } pixels -= linePtr->pixels[2 * pixelReference]; } + + /* + * Check for any start/end offset for this text widget. + */ + + if (textPtr->start != NULL) { + int lineBoundary = TkBTreeLinesTo(NULL, textPtr->start); + + if (TkBTreeLinesTo(NULL, linePtr) < lineBoundary) { + linePtr = TkBTreeFindLine(tree, NULL, lineBoundary); + } + } + if (textPtr->end != NULL) { + int lineBoundary = TkBTreeLinesTo(NULL, textPtr->end); + + if (TkBTreeLinesTo(NULL, linePtr) > lineBoundary) { + linePtr = TkBTreeFindLine(tree, NULL, lineBoundary); + } + } + if (pixelOffset != NULL && linePtr != NULL) { *pixelOffset = pixels; } return linePtr; } Index: generic/tkTextDisp.c ================================================================== --- generic/tkTextDisp.c +++ generic/tkTextDisp.c @@ -4,12 +4,12 @@ * This module provides facilities to display text widgets. It is the * only place where information is kept about the screen layout of text * widgets. (Well, strictly, each TkTextLine and B-tree node caches its * last observed pixel height, but that information originates here). * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -6180,11 +6180,11 @@ */ pickPlace = 0; if (Tcl_GetString(objv[2])[0] == '-') { const char *switchStr = - TkGetStringFromObj(objv[2], &switchLength); + Tcl_GetStringFromObj(objv[2], &switchLength); if ((switchLength >= 2) && (strncmp(switchStr, "-pickplace", (unsigned) switchLength) == 0)) { pickPlace = 1; if (objc != 4) { @@ -7654,19 +7654,19 @@ tkfont = chunkPtr->stylePtr->sValuePtr->tkfont; #ifdef TK_LAYOUT_WITH_BASE_CHUNKS if (baseCharChunkPtr == NULL) { baseCharChunkPtr = chunkPtr; - bciPtr = ckalloc(sizeof(BaseCharInfo)); + bciPtr = (BaseCharInfo *)ckalloc(sizeof(BaseCharInfo)); baseString = &bciPtr->baseChars; Tcl_DStringInit(baseString); bciPtr->width = 0; ciPtr = &bciPtr->ci; } else { - bciPtr = baseCharChunkPtr->clientData; - ciPtr = ckalloc(sizeof(CharInfo)); + bciPtr = (BaseCharInfo *)baseCharChunkPtr->clientData; + ciPtr = (CharInfo *)ckalloc(sizeof(CharInfo)); baseString = &bciPtr->baseChars; } lineOffset = Tcl_DStringLength(baseString); line = Tcl_DStringAppend(baseString,p,maxBytes); @@ -7986,11 +7986,11 @@ return; } #ifdef TK_DRAW_IN_CONTEXT - bciPtr = ciPtr->baseChunkPtr->clientData; + bciPtr = (BaseCharInfo *)ciPtr->baseChunkPtr->clientData; numBytes = Tcl_DStringLength(&bciPtr->baseChars); string = Tcl_DStringValue(&bciPtr->baseChars); #elif defined(TK_LAYOUT_WITH_BASE_CHUNKS) if (ciPtr->baseChunkPtr != chunkPtr) { @@ -8897,11 +8897,11 @@ #endif /* TK_DRAW_IN_CONTEXT */ if (chunkPtr->displayProc != CharDisplayProc) { continue; } - ciPtr = chunkPtr->clientData; + ciPtr = (CharInfo *)chunkPtr->clientData; if (ciPtr->baseChunkPtr != baseCharChunkPtr) { break; } ciPtr->chars = baseChars + ciPtr->baseOffset; @@ -8914,11 +8914,11 @@ } #endif /* TK_DRAW_IN_CONTEXT */ } if (addChunkPtr != NULL) { - ciPtr = addChunkPtr->clientData; + ciPtr = (CharInfo *)addChunkPtr->clientData; ciPtr->chars = baseChars + ciPtr->baseOffset; #ifdef TK_DRAW_IN_CONTEXT addChunkPtr->x += widthAdjust; CharChunkMeasureChars(addChunkPtr, NULL, 0, 0, -1, 0, -1, 0, @@ -8965,11 +8965,11 @@ for (chunkPtr=baseChunkPtr; chunkPtr!=NULL; chunkPtr=chunkPtr->nextPtr) { if (chunkPtr->undisplayProc != CharUndisplayProc) { continue; } - ciPtr = chunkPtr->clientData; + ciPtr = (CharInfo *)chunkPtr->clientData; if (ciPtr->baseChunkPtr != baseChunkPtr) { break; } ciPtr->baseChunkPtr = NULL; @@ -9085,18 +9085,18 @@ /* * Reinstitute this base chunk for re-layout. */ - ciPtr = chunkPtr->clientData; + ciPtr = (CharInfo *)chunkPtr->clientData; baseCharChunkPtr = ciPtr->baseChunkPtr; /* * Remove the chunk data from the base chunk data. */ - bciPtr = baseCharChunkPtr->clientData; + bciPtr = (BaseCharInfo *)baseCharChunkPtr->clientData; #ifdef DEBUG_LAYOUT_WITH_BASE_CHUNKS if ((ciPtr->baseOffset + ciPtr->numBytes) != Tcl_DStringLength(&bciPtr->baseChars)) { fprintf(stderr,"RemoveFromBaseChunk called with wrong chunk " Index: generic/tkTextImage.c ================================================================== --- generic/tkTextImage.c +++ generic/tkTextImage.c @@ -2,11 +2,11 @@ * tkImage.c -- * * This file contains code that allows images to be nested inside text * widgets. It also implements the "image" widget command for texts. * - * Copyright (c) 1997 Sun Microsystems, Inc. + * Copyright © 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -767,13 +767,13 @@ * * Given the name of an embedded image within a text widget, returns an * index corresponding to the image's position in the text. * * Results: - * The return value is 1 if there is an embedded image by the given name - * in the text widget, 0 otherwise. If the image exists, *indexPtr is - * filled in with its index. + * The return value is TCL_OK if there is an embedded image by the given + * name in the text widget, TCL_ERROR otherwise. If the image exists, + * *indexPtr is filled in with its index. * * Side effects: * None. * *-------------------------------------------------------------- @@ -787,22 +787,33 @@ { Tcl_HashEntry *hPtr; TkTextSegment *eiPtr; if (textPtr == NULL) { - return 0; + return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->imageTable, name); if (hPtr == NULL) { - return 0; + return TCL_ERROR; } eiPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr); indexPtr->tree = textPtr->sharedTextPtr->tree; indexPtr->linePtr = eiPtr->body.ei.linePtr; indexPtr->byteIndex = TkTextSegToOffset(eiPtr, indexPtr->linePtr); - return 1; + + /* + * If indexPtr refers to somewhere outside the -startline/-endline + * range limits of the widget, error out since the image indeed is not + * reachable from this text widget (it may be reachable from a peer). + */ + + if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, 1) == TCL_ERROR) { + return TCL_ERROR; + } + + return TCL_OK; } /* *-------------------------------------------------------------- * Index: generic/tkTextIndex.c ================================================================== --- generic/tkTextIndex.c +++ generic/tkTextIndex.c @@ -2,12 +2,12 @@ * tkTextIndex.c -- * * This module provides functions that manipulate indices for text * widgets. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -434,11 +434,11 @@ * falls in the middle of a UTF-8 character, it will be * adjusted to the end of that UTF-8 character. */ start = segPtr->body.chars + (byteIndex - index); - p = TkUtfPrev(start, segPtr->body.chars); + p = Tcl_UtfPrev(start, segPtr->body.chars); p += TkUtfToUniChar(p, &ch); indexPtr->byteIndex += p - start; } break; } @@ -478,11 +478,11 @@ TkTextIndex *indexPtr) /* Structure to fill in. */ { TkTextSegment *segPtr; char *p, *start, *end; int index, offset; - int ch; + Tcl_UniChar ch = 0; indexPtr->tree = tree; if (lineIndex < 0) { lineIndex = 0; charIndex = 0; @@ -525,11 +525,11 @@ if (charIndex == 0) { indexPtr->byteIndex = index; return indexPtr; } charIndex--; - offset = TkUtfToUniChar(p, &ch); + offset = Tcl_UtfToUniChar(p, &ch); index += offset; } } else { if (charIndex < (int)segPtr->size) { indexPtr->byteIndex = index; @@ -759,15 +759,15 @@ if (TkTextMarkNameToIndex(textPtr, string, indexPtr) == TCL_OK) { goto done; } - if (TkTextWindowIndex(textPtr, string, indexPtr) != 0) { + if (TkTextWindowIndex(textPtr, string, indexPtr) == TCL_OK) { goto done; } - if (TkTextImageIndex(textPtr, string, indexPtr) != 0) { + if (TkTextImageIndex(textPtr, string, indexPtr) == TCL_OK) { goto done; } /* *------------------------------------------------ @@ -915,11 +915,11 @@ c = *endOfBase; *endOfBase = 0; result = TkTextWindowIndex(textPtr, Tcl_DStringValue(©), indexPtr); *endOfBase = c; - if (result != 0) { + if (result == TCL_OK) { goto gotBase; } } if ((string[0] == 'e') && (strncmp(string, "end", @@ -952,11 +952,11 @@ c = *endOfBase; *endOfBase = 0; result = TkTextImageIndex(textPtr, Tcl_DStringValue(©), indexPtr); *endOfBase = c; - if (result != 0) { + if (result == TCL_OK) { goto gotBase; } } goto error; @@ -995,18 +995,80 @@ *canCachePtr = canCache; } if (indexPtr->linePtr == NULL) { Tcl_Panic("Bad index created"); } + TkTextIndexAdjustToStartEnd(textPtr, indexPtr, 0); return TCL_OK; error: Tcl_DStringFree(©); Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad text index \"%s\"", string)); Tcl_SetErrorCode(interp, "TK", "TEXT", "BAD_INDEX", NULL); return TCL_ERROR; } + +/* + *--------------------------------------------------------------------------- + * + * TkTextIndexAdjustToStartEnd -- + * + * Adjust indexPtr to the -startline/-endline range, or just check + * if indexPtr is out of this range. + * + * Results: + * The return value is a standard Tcl return result. If check is true, + * return TCL_ERROR if indexPtr is outside the -startline/-endline + * range (indexPtr is not modified). + * If check is false, adjust indexPtr to -startline/-endline. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkTextIndexAdjustToStartEnd( + TkText *textPtr, + TkTextIndex *indexPtr, /* Pointer to index. */ + int check) /* 1 means only check indexPtr against + * the -startline/-endline range + * 0 means adjust to this range */ +{ + int bound; + TkTextIndex indexBound; + + if (!textPtr) { + return TCL_OK; + } + if (textPtr->start != NULL) { + bound = TkBTreeLinesTo(NULL, textPtr->start); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0, + &indexBound); + if (TkTextIndexCmp(indexPtr, &indexBound) < 0) { + if (check) { + return TCL_ERROR; + } + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0, + indexPtr); + } + } + if (textPtr->end != NULL) { + bound = TkBTreeLinesTo(NULL, textPtr->end); + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0, + &indexBound); + if (TkTextIndexCmp(indexPtr, &indexBound) > 0) { + if (check) { + return TCL_ERROR; + } + TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, bound, 0, + indexPtr); + } + } + return TCL_OK; +} /* *--------------------------------------------------------------------------- * * TkTextPrintIndex -- @@ -2124,11 +2186,11 @@ if (!elide) { if (segPtr->typePtr == &tkTextCharType) { start = segPtr->body.chars; end = segPtr->body.chars + segSize; - for (p = end; ; p = TkUtfPrev(p, start)) { + for (p = end; ; p = Tcl_UtfPrev(p, start)) { if (charCount == 0) { dstPtr->byteIndex -= (end - p); goto backwardCharDone; } if (p == start) { @@ -2365,11 +2427,11 @@ if (!Tcl_UniCharIsWordChar(ch)) { break; } if (offset + 1 > 1) { chSize = (segPtr->body.chars + offset - - TkUtfPrev(segPtr->body.chars + offset, + - Tcl_UtfPrev(segPtr->body.chars + offset, segPtr->body.chars)); } firstChar = 0; } if (offset == 0) { Index: generic/tkTextMark.c ================================================================== --- generic/tkTextMark.c +++ generic/tkTextMark.c @@ -2,12 +2,12 @@ * tkTextMark.c -- * * This file contains the functions that implement marks for text * widgets. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -131,11 +131,11 @@ if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 3, objv, "markName ?gravity?"); return TCL_ERROR; } - str = TkGetStringFromObj(objv[3], &length); + str = Tcl_GetStringFromObj(objv[3], &length); if (length == 6 && !strcmp(str, "insert")) { markPtr = textPtr->insertMarkPtr; } else if (length == 7 && !strcmp(str, "current")) { markPtr = textPtr->currentMarkPtr; } else { @@ -158,11 +158,11 @@ typeStr = "left"; } Tcl_SetObjResult(interp, Tcl_NewStringObj(typeStr, -1)); return TCL_OK; } - str = TkGetStringFromObj(objv[4],&length); + str = Tcl_GetStringFromObj(objv[4],&length); c = str[0]; if ((c == 'l') && (strncmp(str, "left", length) == 0)) { newTypePtr = &tkTextLeftMarkType; } else if ((c == 'r') && (strncmp(str, "right", length) == 0)) { @@ -432,12 +432,10 @@ TkText *textPtr, /* Text widget containing mark. */ const char *name, /* Name of mark. */ TkTextIndex *indexPtr) /* Index information gets stored here. */ { TkTextSegment *segPtr; - TkTextIndex index; - int start, end; if (textPtr == NULL) { return TCL_ERROR; } @@ -454,32 +452,21 @@ } segPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr); } TkTextMarkSegToIndex(textPtr, segPtr, indexPtr); - /* If indexPtr refers to somewhere outside the -startline/-endline + /* + * If indexPtr refers to somewhere outside the -startline/-endline * range limits of the widget, error out since the mark indeed is not * reachable from this text widget (it may be reachable from a peer) * (bug 1630271). */ - if (textPtr->start != NULL) { - start = TkBTreeLinesTo(NULL, textPtr->start); - TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, start, 0, - &index); - if (TkTextIndexCmp(indexPtr, &index) < 0) { - return TCL_ERROR; - } - } - if (textPtr->end != NULL) { - end = TkBTreeLinesTo(NULL, textPtr->end); - TkTextMakeByteIndex(textPtr->sharedTextPtr->tree, NULL, end, 0, - &index); - if (TkTextIndexCmp(indexPtr, &index) > 0) { - return TCL_ERROR; - } - } + if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, 1) == TCL_ERROR) { + return TCL_ERROR; + } + return TCL_OK; } /* *-------------------------------------------------------------- Index: generic/tkTextTag.c ================================================================== --- generic/tkTextTag.c +++ generic/tkTextTag.c @@ -3,12 +3,12 @@ * * This module implements the "tag" subcommand of the widget command for * text widgets, plus most of the other high-level functions related to * tags. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1109,11 +1109,11 @@ { Tcl_HashEntry *hPtr; TkSizeT len; const char *str; - str = TkGetStringFromObj(tagName, &len); + str = Tcl_GetStringFromObj(tagName, &len); if (len == 3 && !strcmp(str, "sel")) { return textPtr->selTagPtr; } hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->tagTable, Tcl_GetString(tagName)); Index: generic/tkTextWind.c ================================================================== --- generic/tkTextWind.c +++ generic/tkTextWind.c @@ -3,12 +3,12 @@ * * This file contains code that allows arbitrary windows to be nested * inside text widgets. It also implements the "window" widget command * for texts. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -1318,13 +1318,13 @@ * * Given the name of an embedded window within a text widget, returns an * index corresponding to the window's position in the text. * * Results: - * The return value is 1 if there is an embedded window by the given name - * in the text widget, 0 otherwise. If the window exists, *indexPtr is - * filled in with its index. + * The return value is TCL_OK if there is an embedded window by the given + * name in the text widget, TCL_ERROR otherwise. If the window exists, + * *indexPtr is filled in with its index. * * Side effects: * None. * *-------------------------------------------------------------- @@ -1338,23 +1338,34 @@ { Tcl_HashEntry *hPtr; TkTextSegment *ewPtr; if (textPtr == NULL) { - return 0; + return TCL_ERROR; } hPtr = Tcl_FindHashEntry(&textPtr->sharedTextPtr->windowTable, name); if (hPtr == NULL) { - return 0; + return TCL_ERROR; } ewPtr = (TkTextSegment *)Tcl_GetHashValue(hPtr); indexPtr->tree = textPtr->sharedTextPtr->tree; indexPtr->linePtr = ewPtr->body.ew.linePtr; indexPtr->byteIndex = TkTextSegToOffset(ewPtr, indexPtr->linePtr); - return 1; + + /* + * If indexPtr refers to somewhere outside the -startline/-endline + * range limits of the widget, error out since the window indeed is not + * reachable from this text widget (it may be reachable from a peer). + */ + + if (TkTextIndexAdjustToStartEnd(textPtr, indexPtr, 1) == TCL_ERROR) { + return TCL_ERROR; + } + + return TCL_OK; } /* *-------------------------------------------------------------- * Index: generic/tkTrig.c ================================================================== --- generic/tkTrig.c +++ generic/tkTrig.c @@ -3,12 +3,12 @@ * * This file contains a collection of trigonometry utility routines that * are used by Tk and in particular by the canvas code. It also has * miscellaneous geometry functions used by canvases. * - * Copyright (c) 1992-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1992-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -37,13 +37,13 @@ *-------------------------------------------------------------- */ double TkLineToPoint( - double end1Ptr[2], /* Coordinates of first end-point of line. */ - double end2Ptr[2], /* Coordinates of second end-point of line. */ - double pointPtr[2]) /* Points to coords for point. */ + double end1Ptr[], /* Coordinates of first end-point of line. */ + double end2Ptr[], /* Coordinates of second end-point of line. */ + double pointPtr[]) /* Points to coords for point. */ { double x, y; /* * Compute the point on the line that is closest to the point. This must @@ -141,15 +141,15 @@ *-------------------------------------------------------------- */ int TkLineToArea( - double end1Ptr[2], /* X and y coordinates for one endpoint of + double end1Ptr[], /* X and y coordinates for one endpoint of * line. */ - double end2Ptr[2], /* X and y coordinates for other endpoint of + double end2Ptr[], /* X and y coordinates for other endpoint of * line. */ - double rectPtr[4]) /* Points to coords for rectangle, in the + double rectPtr[]) /* Points to coords for rectangle, in the * order x1, y1, x2, y2. X1 must be no larger * than x2, and y1 no larger than y2. */ { int inside1, inside2; @@ -651,18 +651,18 @@ *-------------------------------------------------------------- */ double TkOvalToPoint( - double ovalPtr[4], /* Pointer to array of four coordinates (x1, + double ovalPtr[], /* Pointer to array of four coordinates (x1, * y1, x2, y2) defining oval's bounding * box. */ double width, /* Width of outline for oval. */ int filled, /* Non-zero means oval should be treated as * filled; zero means only consider * outline. */ - double pointPtr[2]) /* Coordinates of point. */ + double pointPtr[]) /* Coordinates of point. */ { double xDelta, yDelta, scaledDistance, distToOutline, distToCenter; double xDiam, yDiam; /* Index: generic/tkUndo.c ================================================================== --- generic/tkUndo.c +++ generic/tkUndo.c @@ -1,12 +1,12 @@ /* * tkUndo.c -- * * This module provides the implementation of an undo stack. * - * Copyright (c) 2002 by Ludwig Callewaert. - * Copyright (c) 2003-2004 by Vincent Darley. + * Copyright © 2002 Ludwig Callewaert. + * Copyright © 2003-2004 Vincent Darley. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkUndo.h ================================================================== --- generic/tkUndo.h +++ generic/tkUndo.h @@ -1,11 +1,11 @@ /* * tkUndo.h -- * * Declarations shared among the files that implement an undo stack. * - * Copyright (c) 2002 Ludwig Callewaert. + * Copyright © 2002 Ludwig Callewaert. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkUtil.c ================================================================== --- generic/tkUtil.c +++ generic/tkUtil.c @@ -2,12 +2,12 @@ * tkUtil.c -- * * This file contains miscellaneous utility functions that are used by * the rest of Tk, such as a function for drawing a focus highlight. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -729,11 +729,11 @@ * any. */ int *intPtr) /* Filled in with number of pages or lines to * scroll, if any. */ { TkSizeT length; - const char *arg = TkGetStringFromObj(objv[2], &length); + const char *arg = Tcl_GetStringFromObj(objv[2], &length); #define ArgPfxEq(str) \ ((arg[0] == str[0]) && !strncmp(arg, str, length)) if (ArgPfxEq("moveto")) { @@ -757,11 +757,11 @@ *intPtr = (d >= 0) ? ceil(d) : floor(d); if (dblPtr) { *dblPtr = d; } - arg = TkGetStringFromObj(objv[4], &length); + arg = Tcl_GetStringFromObj(objv[4], &length); if (ArgPfxEq("pages")) { return TK_SCROLL_PAGES; } else if (ArgPfxEq("units")) { return TK_SCROLL_UNITS; } @@ -1190,15 +1190,17 @@ event.general.xany.send_event = False; event.general.xany.window = Tk_WindowId(target); event.general.xany.display = Tk_Display(target); event.virt.name = Tk_GetUid(eventName); event.virt.user_data = detail; + if (detail) Tcl_IncrRefCount(detail); // Event code will DecrRefCount Tk_QueueWindowEvent(&event.general, TCL_QUEUE_TAIL); } -#if TCL_UTF_MAX <= 4 +/* Tcl 8.6 has a different definition of Tcl_UniChar than other Tcl versions for TCL_UTF_MAX > 3 */ +#if TCL_UTF_MAX <= (3 + (TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 6)) /* *--------------------------------------------------------------------------- * * TkUtfToUniChar -- * @@ -1223,19 +1225,14 @@ * the UTF-8 string. */ { Tcl_UniChar uniChar = 0; size_t len = Tcl_UtfToUniChar(src, &uniChar); - if ((sizeof(Tcl_UniChar) == 2) - && ((uniChar & 0xFC00) == 0xD800) -#if TCL_MAJOR_VERSION > 8 - && (len == 1) -#endif - ) { + if ((uniChar & 0xFC00) == 0xD800) { Tcl_UniChar low = uniChar; - /* This can only happen if Tcl is compiled with TCL_UTF_MAX=4, - * or when a high surrogate character is detected in UTF-8 form */ + /* This can only happen if sizeof(Tcl_UniChar)== 2 and src points + * to a character > U+FFFF */ size_t len2 = Tcl_UtfToUniChar(src+len, &low); if ((low & 0xFC00) == 0xDC00) { *chPtr = (((uniChar & 0x3FF) << 10) | (low & 0x3FF)) + 0x10000; return len + len2; } @@ -1263,72 +1260,21 @@ *--------------------------------------------------------------------------- */ size_t TkUniCharToUtf(int ch, char *buf) { - if ((sizeof(Tcl_UniChar) == 2) && (((unsigned)(ch - 0x10000) <= 0xFFFFF))) { + if ((unsigned)(ch - 0x10000) <= 0xFFFFF) { /* Spit out a 4-byte UTF-8 character or 2 x 3-byte UTF-8 characters, depending on Tcl * version and/or TCL_UTF_MAX build value */ int len = Tcl_UniCharToUtf(0xD800 | ((ch - 0x10000) >> 10), buf); return len + Tcl_UniCharToUtf(0xDC00 | (ch & 0x7FF), buf + len); } return Tcl_UniCharToUtf(ch, buf); } -/* - *--------------------------------------------------------------------------- - * - * TkUtfPrev -- - * - * Almost the same as Tcl_UtfPrev. - * This function is capable of jumping over a upper/lower surrogate pair. - * So, might jump back up to 6 bytes. - * - * Results: - * pointer to the first byte of the current UTF-8 character. A surrogate - * pair is also handled as being a single entity. - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ - -const char * -TkUtfPrev( - const char *src, /* The UTF-8 string. */ - const char *start) /* Start position of string */ -{ - const char *p = Tcl_UtfPrev(src, start); - const char *first = Tcl_UtfPrev(p, start); - int ch; - -#if TCL_UTF_MAX == 3 - if ((src - start > 3) && ((src[-1] & 0xC0) == 0x80) && ((src[-2] & 0xC0) == 0x80) - && ((src[-3] & 0xC0) == 0x80) && (UCHAR(src[-4]) >= 0xF0)) { - return src - 4; - } -#endif - - return (first + TkUtfToUniChar(first, &ch) >= src) ? first : p ; -} - -#endif - -#if TCL_MAJOR_VERSION > 8 -unsigned char * -TkGetByteArrayFromObj( - Tcl_Obj *objPtr, - size_t *lengthPtr -) { - unsigned char *result = Tcl_GetByteArrayFromObj(objPtr, NULL); - *lengthPtr = *(size_t *) objPtr->internalRep.twoPtrValue.ptr1; - return result; -} -#endif /* TCL_MAJOR_VERSION > 8 */ - +#endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ Index: generic/tkVisual.c ================================================================== --- generic/tkVisual.c +++ generic/tkVisual.c @@ -3,12 +3,12 @@ * * This file contains library procedures for allocating and freeing * visuals and colormaps. This code is based on a prototype * implementation by Paul Mackerras. * - * Copyright (c) 1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: generic/tkWindow.c ================================================================== --- generic/tkWindow.c +++ generic/tkWindow.c @@ -3,12 +3,12 @@ * * This file provides basic window-manipulation functions, which are * equivalent to functions in Xlib (and even invoke them) but also * maintain the local Tk_Window structure. * - * Copyright (c) 1989-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright © 1989-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -91,10 +91,11 @@ #define ISSAFE 1 #define PASSMAINWINDOW 2 #define WINMACONLY 4 #define USEINITPROC 8 +#define SAVEUPDATECMD 16 /* better only be one of these! */ typedef int (TkInitProc)(Tcl_Interp *interp, ClientData clientData); typedef struct { const char *name; /* Name of command. */ Tcl_ObjCmdProc *objProc; /* Command's object- (or string-) based @@ -124,11 +125,11 @@ {"place", Tk_PlaceObjCmd, PASSMAINWINDOW|ISSAFE}, {"raise", Tk_RaiseObjCmd, PASSMAINWINDOW|ISSAFE}, {"selection", Tk_SelectionObjCmd, PASSMAINWINDOW}, {"tk", (Tcl_ObjCmdProc *)(void *)TkInitTkCmd, USEINITPROC|PASSMAINWINDOW|ISSAFE}, {"tkwait", Tk_TkwaitObjCmd, PASSMAINWINDOW|ISSAFE}, - {"update", Tk_UpdateObjCmd, PASSMAINWINDOW|ISSAFE}, + {"update", Tk_UpdateObjCmd, PASSMAINWINDOW|ISSAFE|SAVEUPDATECMD}, {"winfo", Tk_WinfoObjCmd, PASSMAINWINDOW|ISSAFE}, {"wm", Tk_WmObjCmd, PASSMAINWINDOW}, /* * Default widget class commands. @@ -332,13 +333,13 @@ /* * Create built-in photo image formats. */ - Tk_CreatePhotoImageFormat(&tkImgFmtDefault); - Tk_CreatePhotoImageFormat(&tkImgFmtGIF); - Tk_CreatePhotoImageFormat(&tkImgFmtPNG); + Tk_CreatePhotoImageFormat(&tkImgFmtDefault); + Tk_CreatePhotoImageFormatVersion3(&tkImgFmtGIF); + Tk_CreatePhotoImageFormatVersion3(&tkImgFmtPNG); Tk_CreatePhotoImageFormat(&tkImgFmtPPM); Tk_CreatePhotoImageFormat(&tkImgFmtSVGnano); } if ((parent != NULL) && (screenName != NULL) && (screenName[0] == '\0')) { @@ -874,10 +875,11 @@ mainPtr->displayFocusPtr = NULL; mainPtr->optionRootPtr = NULL; Tcl_InitHashTable(&mainPtr->imageTable, TCL_STRING_KEYS); mainPtr->strictMotif = 0; mainPtr->alwaysShowSelection = 0; + mainPtr->tclUpdateObjProc = NULL; if (Tcl_LinkVar(interp, "tk_strictMotif", (char *) &mainPtr->strictMotif, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } if (Tcl_CreateNamespace(interp, "::tk", NULL, NULL) == NULL) { @@ -913,16 +915,18 @@ * Bind in Tk's commands. */ isSafe = Tcl_IsSafe(interp); for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { + Tcl_CmdInfo cmdInfo; + if (cmdPtr->objProc == NULL) { Tcl_Panic("TkCreateMainWindow: builtin command with NULL string and object procs"); } #if defined(_WIN32) && !defined(STATIC_BUILD) - if ((cmdPtr->flags & WINMACONLY) && tclStubsPtr->reserved9) { + if ((cmdPtr->flags & WINMACONLY) && tclStubsPtr->tcl_CreateFileHandler) { /* * We are running on Cygwin, so don't use the win32 dialogs. */ continue; @@ -932,10 +936,15 @@ if (cmdPtr->flags & PASSMAINWINDOW) { clientData = tkwin; } else { clientData = NULL; } + if ((cmdPtr->flags & SAVEUPDATECMD) && + Tcl_GetCommandInfo(interp, cmdPtr->name, &cmdInfo) && + cmdInfo.isNativeObjectProc && !cmdInfo.objClientData && !cmdInfo.deleteProc) { + mainPtr->tclUpdateObjProc = cmdInfo.objProc; + } if (cmdPtr->flags & USEINITPROC) { ((TkInitProc *)(void *)cmdPtr->objProc)(interp, clientData); } else { Tcl_CreateObjCommand(interp, cmdPtr->name, cmdPtr->objProc, clientData, NULL); @@ -1266,11 +1275,11 @@ tsdPtr->halfdeadWindowList = halfdeadPtr; } /* * Some cleanup needs to be done immediately, rather than later, because - * it needs information that will be destoyed before we get to the main + * it needs information that will be destroyed before we get to the main * cleanup point. For example, TkFocusDeadWindow needs to access the * parentPtr field from a window, but if a Destroy event handler deletes * the window's parent this field will be NULL before the main cleanup * point is reached. */ @@ -1494,14 +1503,24 @@ * being deleted. If it *is*, the interpreter cleanup will do all * the needed work. */ if ((winPtr->mainPtr->interp != NULL) && - !Tcl_InterpDeleted(winPtr->mainPtr->interp)) { + !Tcl_InterpDeleted(winPtr->mainPtr->interp)) { for (cmdPtr = commands; cmdPtr->name != NULL; cmdPtr++) { - Tcl_CreateObjCommand(winPtr->mainPtr->interp, cmdPtr->name, - TkDeadAppObjCmd, NULL, NULL); + if ((cmdPtr->flags & SAVEUPDATECMD) && + winPtr->mainPtr->tclUpdateObjProc != NULL) { + /* Restore Tcl's version of [update] */ + Tcl_CreateObjCommand(winPtr->mainPtr->interp, + cmdPtr->name, + winPtr->mainPtr->tclUpdateObjProc, + NULL, NULL); + } else { + Tcl_CreateObjCommand(winPtr->mainPtr->interp, + cmdPtr->name, TkDeadAppObjCmd, + NULL, NULL); + } } Tcl_CreateObjCommand(winPtr->mainPtr->interp, "send", TkDeadAppObjCmd, NULL, NULL); Tcl_UnlinkVar(winPtr->mainPtr->interp, "tk_strictMotif"); Tcl_UnlinkVar(winPtr->mainPtr->interp, @@ -3199,11 +3218,11 @@ * The -class argument is always the ToTitle of the -name */ { TkSizeT numBytes; - const char *bytes = TkGetStringFromObj(nameObj, &numBytes); + const char *bytes = Tcl_GetStringFromObj(nameObj, &numBytes); classObj = Tcl_NewStringObj(bytes, numBytes); numBytes = Tcl_UtfToTitle(Tcl_GetString(classObj)); Tcl_SetObjLength(classObj, numBytes); @@ -3281,14 +3300,18 @@ goto done; } } /* - * Provide Tk and its stub table. + * Provide "tk" and its stub table. */ - code = Tcl_PkgProvideEx(interp, "Tk", TK_PATCH_LEVEL, +#ifndef TK_NO_DEPRECATED + Tcl_PkgProvideEx(interp, "Tk", TK_PATCH_LEVEL, + (ClientData) &tkStubs); +#endif + code = Tcl_PkgProvideEx(interp, "tk", TK_PATCH_LEVEL, (ClientData) &tkStubs); if (code != TCL_OK) { goto done; } @@ -3379,11 +3402,11 @@ Tk_PkgInitStubsCheck( Tcl_Interp *interp, const char * version, int exact) { - const char *actualVersion = Tcl_PkgRequireEx(interp, "Tk", version, 0, NULL); + const char *actualVersion = Tcl_PkgRequireEx(interp, "tk", version, 0, NULL); if (exact && actualVersion) { const char *p = version; int count = 0; @@ -3391,15 +3414,15 @@ count += !isdigit(UCHAR(*p++)); } if (count == 1) { if (0 != strncmp(version, actualVersion, strlen(version))) { /* Construct error message */ - Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL); + Tcl_PkgPresentEx(interp, "tk", version, 1, NULL); return NULL; } } else { - return Tcl_PkgPresentEx(interp, "Tk", version, 1, NULL); + return Tcl_PkgPresentEx(interp, "tk", version, 1, NULL); } } return actualVersion; } Index: generic/ttk/ttkButton.c ================================================================== --- generic/ttk/ttkButton.c +++ generic/ttk/ttkButton.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003, Joe English * * label, button, checkbutton, radiobutton, and menubutton widgets. */ #include "tkInt.h" @@ -22,11 +22,11 @@ * Text element resources: */ Tcl_Obj *textObj; Tcl_Obj *justifyObj; Tcl_Obj *textVariableObj; - Tcl_Obj *underlineObj; + int underline; Tcl_Obj *widthObj; Ttk_TraceHandle *textVariableTrace; Ttk_ImageSpec *imageSpec; @@ -63,13 +63,12 @@ offsetof(Base,base.textObj), TCL_INDEX_NONE, 0,0,GEOMETRY_CHANGED }, {TK_OPTION_STRING, "-textvariable", "textVariable", "Variable", "", offsetof(Base,base.textVariableObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, - {TK_OPTION_INT, "-underline", "underline", "Underline", - "-1", offsetof(Base,base.underlineObj), TCL_INDEX_NONE, - 0,0,0 }, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(Base, base.underline), 0}, /* SB: OPTION_INT, see <> */ {TK_OPTION_STRING, "-width", "width", "Width", NULL, offsetof(Base,base.widthObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,0,GEOMETRY_CHANGED }, @@ -271,15 +270,16 @@ WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(BaseOptionSpecs) }; static const Ttk_Ensemble LabelCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, - { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; static const WidgetSpec LabelWidgetSpec = { @@ -376,16 +376,17 @@ } return Tcl_EvalObjEx(interp, buttonPtr->button.commandObj, TCL_EVAL_GLOBAL); } static const Ttk_Ensemble ButtonCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, - { "invoke", ButtonInvokeCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, + { "invoke", ButtonInvokeCommand,0 }, { "state", TtkWidgetStateCommand,0 }, - { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; static const WidgetSpec ButtonWidgetSpec = { @@ -583,16 +584,17 @@ return Tcl_EvalObjEx(interp, checkPtr->checkbutton.commandObj, TCL_EVAL_GLOBAL); } static const Ttk_Ensemble CheckbuttonCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, - { "invoke", CheckbuttonInvokeCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, + { "invoke", CheckbuttonInvokeCommand,0 }, { "state", TtkWidgetStateCommand,0 }, - { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, /* MISSING: select, deselect, toggle */ { 0,0,0 } }; static const WidgetSpec CheckbuttonWidgetSpec = @@ -759,16 +761,17 @@ return Tcl_EvalObjEx(interp, radioPtr->radiobutton.commandObj, TCL_EVAL_GLOBAL); } static const Ttk_Ensemble RadiobuttonCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, - { "invoke", RadiobuttonInvokeCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, + { "invoke", RadiobuttonInvokeCommand,0 }, { "state", TtkWidgetStateCommand,0 }, - { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, /* MISSING: select, deselect */ { 0,0,0 } }; static const WidgetSpec RadiobuttonWidgetSpec = @@ -833,10 +836,11 @@ { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; static const WidgetSpec MenubuttonWidgetSpec = { Index: generic/ttk/ttkCache.c ================================================================== --- generic/ttk/ttkCache.c +++ generic/ttk/ttkCache.c @@ -1,9 +1,9 @@ /* * Theme engine resource cache. * - * Copyright (c) 2004, Joe English + * Copyright © 2004, Joe English * * The problem: * * Tk maintains reference counts for fonts, colors, and images, * and deallocates them when the reference count goes to zero. Index: generic/ttk/ttkClamTheme.c ================================================================== --- generic/ttk/ttkClamTheme.c +++ generic/ttk/ttkClamTheme.c @@ -1,7 +1,7 @@ /* - * Copyright (C) 2004 Joe English + * Copyright © 2004 Joe English * * "clam" theme; inspired by the XFCE family of Gnome themes. */ #include "tkInt.h" Index: generic/ttk/ttkClassicTheme.c ================================================================== --- generic/ttk/ttkClassicTheme.c +++ generic/ttk/ttkClassicTheme.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004, Joe English * * "classic" theme; implements the classic Motif-like Tk look. * */ Index: generic/ttk/ttkDecls.h ================================================================== --- generic/ttk/ttkDecls.h +++ generic/ttk/ttkDecls.h @@ -11,11 +11,15 @@ Tcl_Interp *, const char *version, int epoch, int revision); #define Ttk_InitStubs(interp) TtkInitializeStubs( \ interp, TTK_VERSION, TTK_STUBS_EPOCH, TTK_STUBS_REVISION) #else -#define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "Ttk", TTK_VERSION, 0, NULL) +#if !defined(TK_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 +# define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "Ttk", TTK_VERSION, 0, NULL) +#else +# define Ttk_InitStubs(interp) Tcl_PkgRequireEx(interp, "ttk", TTK_VERSION, 0, NULL) +#endif #endif #if !defined(BUILD_tk) # define TTK_DEPRECATED(msg) TTKAPI TCL_DEPRECATED_API(msg) Index: generic/ttk/ttkDefaultTheme.c ================================================================== --- generic/ttk/ttkDefaultTheme.c +++ generic/ttk/ttkDefaultTheme.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003 Joe English * * Tk alternate theme, intended to match the MSUE and Gtk's (old) default theme */ #include "tkInt.h" Index: generic/ttk/ttkElements.c ================================================================== --- generic/ttk/ttkElements.c +++ generic/ttk/ttkElements.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003 Joe English * * Default implementation for themed elements. * */ Index: generic/ttk/ttkEntry.c ================================================================== --- generic/ttk/ttkEntry.c +++ generic/ttk/ttkEntry.c @@ -1,13 +1,13 @@ /* * DERIVED FROM: tk/generic/tkEntry.c r1.35. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright (c) 2000 Ajuba Solutions. - * Copyright (c) 2002 ActiveState Corporation. - * Copyright (c) 2004 Joe English + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2000 Ajuba Solutions. + * Copyright © 2002 ActiveState Corporation. + * Copyright © 2004 Joe English */ #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -323,11 +323,11 @@ Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj), entryPtr->entry.displayString, entryPtr->entry.numChars, 0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES, &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight); } else { - text = TkGetStringFromObj(entryPtr->entry.placeholderObj, &length); + text = Tcl_GetStringFromObj(entryPtr->entry.placeholderObj, &length); entryPtr->entry.textLayout = Tk_ComputeTextLayout( Tk_GetFontFromObj(entryPtr->core.tkwin, entryPtr->entry.fontObj), text, length, 0/*wraplength*/, entryPtr->entry.justify, TK_IGNORE_NEWLINES, &entryPtr->entry.layoutWidth, &entryPtr->entry.layoutHeight); @@ -1310,11 +1310,11 @@ } else { foregroundObj = es.foregroundObj; } /* Use placeholder text width */ leftIndex = 0; - (void)TkGetStringFromObj(entryPtr->entry.placeholderObj, &rightIndex); + (void)Tcl_GetStringFromObj(entryPtr->entry.placeholderObj, &rightIndex); } else { foregroundObj = es.foregroundObj; } gc = EntryGetGC(entryPtr, foregroundObj, clipRegion); if (showSelection) { @@ -1391,18 +1391,20 @@ # define EntryWidth(e) (Tk_Width(entryPtr->core.tkwin)) /* Not Right */ TkSizeT length, idx; const char *string; if (TCL_OK == TkGetIntForIndex(indexObj, entryPtr->entry.numChars - 1, 1, &idx)) { - if ((idx != TCL_INDEX_NONE) && (idx > entryPtr->entry.numChars)) { + if (idx == TCL_INDEX_NONE) { + idx = 0; + } else if (idx > entryPtr->entry.numChars) { idx = entryPtr->entry.numChars; } *indexPtr = idx; return TCL_OK; } - string = TkGetStringFromObj(indexObj, &length); + string = Tcl_GetStringFromObj(indexObj, &length); if (strncmp(string, "insert", length) == 0) { *indexPtr = entryPtr->entry.insertPos; } else if (strncmp(string, "left", length) == 0) { /* for debugging */ *indexPtr = entryPtr->entry.xscroll.first; @@ -1743,10 +1745,11 @@ { "index", EntryIndexCommand,0 }, { "insert", EntryInsertCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "selection", 0,EntrySelectionCommands }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { "validate", EntryValidateCommand,0 }, { "xview", EntryXViewCommand,0 }, { 0,0,0 } }; @@ -1911,12 +1914,13 @@ { "identify", TtkWidgetIdentifyCommand,0 }, { "index", EntryIndexCommand,0 }, { "insert", EntryInsertCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "selection", 0,EntrySelectionCommands }, - { "state", TtkWidgetStateCommand,0 }, { "set", EntrySetCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { "validate", EntryValidateCommand,0 }, { "xview", EntryXViewCommand,0 }, { 0,0,0 } }; @@ -2023,12 +2027,13 @@ { "identify", TtkWidgetIdentifyCommand,0 }, { "index", EntryIndexCommand,0 }, { "insert", EntryInsertCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "selection", 0,EntrySelectionCommands }, - { "state", TtkWidgetStateCommand,0 }, { "set", EntrySetCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { "validate", EntryValidateCommand,0 }, { "xview", EntryXViewCommand,0 }, { 0,0,0 } }; Index: generic/ttk/ttkFrame.c ================================================================== --- generic/ttk/ttkFrame.c +++ generic/ttk/ttkFrame.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004 Joe English * * ttk::frame and ttk::labelframe widgets. */ #include "tkInt.h" @@ -46,15 +46,16 @@ WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; static const Ttk_Ensemble FrameCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, - { "identify", TtkWidgetIdentifyCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /* * FrameMargins -- @@ -232,11 +233,11 @@ * Labelframe widget record: */ typedef struct { Tcl_Obj *labelAnchorObj; Tcl_Obj *textObj; - Tcl_Obj *underlineObj; + int underline; Tk_Window labelWidget; Ttk_Manager *mgr; Ttk_Layout labelLayout; /* Sublayout for label */ Ttk_Box labelParcel; /* Set in layoutProc */ @@ -255,13 +256,12 @@ "nw", offsetof(Labelframe, label.labelAnchorObj),TCL_INDEX_NONE, 0,0,GEOMETRY_CHANGED}, {TK_OPTION_STRING, "-text", "text", "Text", "", offsetof(Labelframe,label.textObj), TCL_INDEX_NONE, 0,0,GEOMETRY_CHANGED }, - {TK_OPTION_INT, "-underline", "underline", "Underline", - "-1", offsetof(Labelframe,label.underlineObj), TCL_INDEX_NONE, - 0,0,0 }, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(Labelframe, label.underline), 0}, {TK_OPTION_WINDOW, "-labelwidget", "labelWidget", "LabelWidget", NULL, TCL_INDEX_NONE, offsetof(Labelframe,label.labelWidget), TK_OPTION_NULL_OK,0,LABELWIDGET_CHANGED|GEOMETRY_CHANGED }, WIDGET_INHERIT_OPTIONS(FrameOptionSpecs) Index: generic/ttk/ttkImage.c ================================================================== --- generic/ttk/ttkImage.c +++ generic/ttk/ttkImage.c @@ -1,10 +1,10 @@ /* * Image specifications and image element factory. * - * Copyright (C) 2004 Pat Thoyts - * Copyright (C) 2004 Joe English + * Copyright © 2004 Pat Thoyts + * Copyright © 2004 Joe English * * An imageSpec is a multi-element list; the first element * is the name of the default image to use, the remainder of the * list is a sequence of statespec/imagename options as per * [style map]. Index: generic/ttk/ttkInit.c ================================================================== --- generic/ttk/ttkInit.c +++ generic/ttk/ttkInit.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003 Joe English * * Ttk package: initialization routine and miscellaneous utilities. */ #include "tkInt.h" @@ -269,11 +269,14 @@ RegisterWidgets(interp); RegisterThemes(interp); Ttk_PlatformInit(interp); +#ifndef TK_NO_DEPRECATED Tcl_PkgProvideEx(interp, "Ttk", TTK_PATCH_LEVEL, (void *)&ttkStubs); +#endif + Tcl_PkgProvideEx(interp, "ttk", TTK_PATCH_LEVEL, (void *)&ttkStubs); return TCL_OK; } /*EOF*/ Index: generic/ttk/ttkLabel.c ================================================================== --- generic/ttk/ttkLabel.c +++ generic/ttk/ttkLabel.c @@ -51,12 +51,16 @@ offsetof(TextElement,textObj), "" }, { "-font", TK_OPTION_FONT, offsetof(TextElement,fontObj), DEFAULT_FONT }, { "-foreground", TK_OPTION_COLOR, offsetof(TextElement,foregroundObj), "black" }, - { "-underline", TK_OPTION_INT, + { "-underline", TK_OPTION_INDEX, +#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) offsetof(TextElement,underlineObj), "-1"}, +#else + offsetof(TextElement,underlineObj), NULL}, +#endif { "-width", TK_OPTION_INT, offsetof(TextElement,widthObj), "-1"}, { "-anchor", TK_OPTION_ANCHOR, offsetof(TextElement,anchorObj), "w"}, { "-justify", TK_OPTION_JUSTIFY, @@ -124,11 +128,11 @@ * Called by TextElementDraw() and LabelElementDraw(). */ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) { XColor *color = Tk_GetColorFromObj(tkwin, text->foregroundObj); - int underline = -1; + TkSizeT underline = TCL_INDEX_NONE; XGCValues gcValues; GC gc1, gc2; Tk_Anchor anchor = TK_ANCHOR_CENTER; TkRegion clipRegion = NULL; @@ -168,18 +172,23 @@ text->textLayout, b.x+1, b.y+1, 0/*firstChar*/, -1/*lastChar*/); } Tk_DrawTextLayout(Tk_Display(tkwin), d, gc1, text->textLayout, b.x, b.y, 0/*firstChar*/, -1/*lastChar*/); - Tcl_GetIntFromObj(NULL, text->underlineObj, &underline); - if (underline >= 0) { - if (text->embossed) { - Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2, - text->textLayout, b.x+1, b.y+1, underline); - } - Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1, - text->textLayout, b.x, b.y, underline); + if (text->underlineObj != NULL) { + TkGetIntForIndex(text->underlineObj, TCL_INDEX_END, 0, &underline); + if (underline != TCL_INDEX_NONE) { + if ((size_t)underline > (size_t)TCL_INDEX_END>>1) { + underline++; + } + if (text->embossed) { + Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc2, + text->textLayout, b.x+1, b.y+1, underline); + } + Tk_UnderlineTextLayout(Tk_Display(tkwin), d, gc1, + text->textLayout, b.x, b.y, underline); + } } if (clipRegion != NULL) { #ifdef HAVE_XFT TkUnixSetXftClipRegion(NULL); @@ -461,12 +470,16 @@ offsetof(LabelElement,text.textObj), "" }, { "-font", TK_OPTION_FONT, offsetof(LabelElement,text.fontObj), DEFAULT_FONT }, { "-foreground", TK_OPTION_COLOR, offsetof(LabelElement,text.foregroundObj), "black" }, - { "-underline", TK_OPTION_INT, + { "-underline", TK_OPTION_INDEX, +#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) offsetof(LabelElement,text.underlineObj), "-1"}, +#else + offsetof(LabelElement,text.underlineObj), NULL}, +#endif { "-width", TK_OPTION_INT, offsetof(LabelElement,text.widthObj), ""}, { "-anchor", TK_OPTION_ANCHOR, offsetof(LabelElement,text.anchorObj), "w"}, { "-justify", TK_OPTION_JUSTIFY, Index: generic/ttk/ttkLayout.c ================================================================== --- generic/ttk/ttkLayout.c +++ generic/ttk/ttkLayout.c @@ -1,11 +1,11 @@ /* * ttkLayout.c -- * * Generic layout processing. * - * Copyright (c) 2003 Joe English. Freely redistributable. + * Copyright © 2003 Joe English. Freely redistributable. */ #include "tkInt.h" #include "ttkThemeInt.h" Index: generic/ttk/ttkManager.c ================================================================== --- generic/ttk/ttkManager.c +++ generic/ttk/ttkManager.c @@ -450,11 +450,11 @@ Tk_Window tkwin; /* Try interpreting as an integer first: */ if (TkGetIntForIndex(objPtr, mgr->nContent - 1, 1, &index) == TCL_OK) { - if (index + 1 > mgr->nContent + 1) { + if (index == TCL_INDEX_NONE || index > mgr->nContent) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "Managed window index %d out of bounds", (int)index)); Tcl_SetErrorCode(interp, "TTK", "MANAGED", "INDEX", NULL); return TCL_ERROR; } Index: generic/ttk/ttkManager.h ================================================================== --- generic/ttk/ttkManager.h +++ generic/ttk/ttkManager.h @@ -1,7 +1,7 @@ /* - * Copyright (c) 2005, Joe English. Freely redistributable. + * Copyright © 2005 Joe English. Freely redistributable. * * Geometry manager utilities. */ #ifndef _TTKMANAGER Index: generic/ttk/ttkNotebook.c ================================================================== --- generic/ttk/ttkNotebook.c +++ generic/ttk/ttkNotebook.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004 Joe English */ #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" @@ -42,11 +42,11 @@ /* Label options: */ Tcl_Obj *textObj; Tcl_Obj *imageObj; Tcl_Obj *compoundObj; - Tcl_Obj *underlineObj; + int underline; } Tab; /* Two different option tables are used for tabs: * TabOptionSpecs is used to draw the tab, and only includes resources @@ -65,12 +65,12 @@ {TK_OPTION_STRING, "-image", "image", "Image", NULL/*default*/, offsetof(Tab,imageObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK, 0, GEOMETRY_CHANGED }, {TK_OPTION_STRING_TABLE, "-compound", "compound", "Compound", NULL, offsetof(Tab,compoundObj), TCL_INDEX_NONE, TK_OPTION_NULL_OK,(void *)ttkCompoundStrings,GEOMETRY_CHANGED }, - {TK_OPTION_INT, "-underline", "underline", "Underline", "-1", - offsetof(Tab,underlineObj), TCL_INDEX_NONE, 0, 0, GEOMETRY_CHANGED }, + {TK_OPTION_INDEX, "-underline", "underline", "Underline", + TK_OPTION_UNDERLINE_DEF(Tab, underline), GEOMETRY_CHANGED}, {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0 } }; static const Tk_OptionSpec PaneOptionSpecs[] = { @@ -1104,11 +1104,13 @@ Tcl_SetObjResult(interp, Tcl_NewStringObj(elementName, -1)); } break; case IDENTIFY_TAB: +#if !defined TK_NO_DEPRECATED && (TCL_MAJOR_VERSION < 9) if (tabIndex != TCL_INDEX_NONE) +#endif Tcl_SetObjResult(interp, TkNewIndexObj(tabIndex)); break; } return TCL_OK; } @@ -1130,11 +1132,13 @@ return TCL_ERROR; } status = FindTabIndex(interp, nb, objv[2], &index); if (status == TCL_OK) { +#if !defined(TK_NO_DEPRECATED) && (TCL_MAJOR_VERSION < 9) if (index != TCL_INDEX_NONE) +#endif Tcl_SetObjResult(interp, TkNewIndexObj(index)); } return status; } @@ -1240,20 +1244,21 @@ /* Subcommand table: */ static const Ttk_Ensemble NotebookCommands[] = { { "add", NotebookAddCommand,0 }, - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "forget", NotebookForgetCommand,0 }, { "hide", NotebookHideCommand,0 }, { "identify", NotebookIdentifyCommand,0 }, { "index", NotebookIndexCommand,0 }, { "insert", NotebookInsertCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "select", NotebookSelectCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { "tab", NotebookTabCommand,0 }, { "tabs", NotebookTabsCommand,0 }, { 0,0,0 } }; Index: generic/ttk/ttkPanedwindow.c ================================================================== --- generic/ttk/ttkPanedwindow.c +++ generic/ttk/ttkPanedwindow.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2005, Joe English. Freely redistributable. + * Copyright © 2005 Joe English. Freely redistributable. * * ttk::panedwindow widget implementation. * * TODO: track active/pressed sash. */ @@ -880,20 +880,21 @@ return TCL_OK; } static const Ttk_Ensemble PanedCommands[] = { { "add", PanedAddCommand,0 }, - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "forget", PanedForgetCommand,0 }, { "identify", PanedIdentifyCommand,0 }, { "insert", PanedInsertCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "pane", PanedPaneCommand,0 }, { "panes", PanedPanesCommand,0 }, { "sashpos", PanedSashposCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /*------------------------------------------------------------------------ * +++ Widget specification. Index: generic/ttk/ttkProgress.c ================================================================== --- generic/ttk/ttkProgress.c +++ generic/ttk/ttkProgress.c @@ -1,7 +1,7 @@ /* - * Copyright (c) Joe English, Pat Thoyts, Michael Kirkham + * Copyright © Joe English, Pat Thoyts, Michael Kirkham * * ttk::progressbar widget. */ #include "tkInt.h" @@ -123,31 +123,32 @@ static void AnimateProgressProc(ClientData clientData) { Progressbar *pb = (Progressbar *)clientData; pb->progress.timer = 0; - if (AnimationEnabled(pb)) { int phase = 0; Tcl_GetIntFromObj(NULL, pb->progress.phaseObj, &phase); /* * Update -phase: */ + ++phase; - if (pb->progress.maxPhase) - phase %= pb->progress.maxPhase; + if (phase > pb->progress.maxPhase) { + phase = 0; + } Tcl_DecrRefCount(pb->progress.phaseObj); pb->progress.phaseObj = Tcl_NewWideIntObj(phase); Tcl_IncrRefCount(pb->progress.phaseObj); /* * Reschedule: */ + pb->progress.timer = Tcl_CreateTimerHandler( pb->progress.period, AnimateProgressProc, clientData); - TtkRedisplayWidget(&pb->core); } } /* CheckAnimation -- @@ -516,18 +517,19 @@ return ProgressbarStartStopCommand( interp, "::ttk::progressbar::stop", objc, objv); } static const Ttk_Ensemble ProgressbarCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "start", ProgressbarStartCommand,0 }, { "state", TtkWidgetStateCommand,0 }, { "step", ProgressbarStepCommand,0 }, { "stop", ProgressbarStopCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /* * Widget specification: Index: generic/ttk/ttkScale.c ================================================================== --- generic/ttk/ttkScale.c +++ generic/ttk/ttkScale.c @@ -1,12 +1,11 @@ /* - * Copyright (C) 2004 Pat Thoyts + * Copyright © 2004 Pat Thoyts * * ttk::scale widget. */ -#include "tkInt.h" #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" #define DEF_SCALE_LENGTH "100" @@ -481,18 +480,19 @@ } return pt; } static const Ttk_Ensemble ScaleCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, - { "state", TtkWidgetStateCommand,0 }, - { "instate", TtkWidgetInstateCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, + { "coords", ScaleCoordsCommand,0 }, + { "get", ScaleGetCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, { "set", ScaleSetCommand,0 }, - { "get", ScaleGetCommand,0 }, - { "coords", ScaleCoordsCommand,0 }, + { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; static const WidgetSpec ScaleWidgetSpec = { Index: generic/ttk/ttkScrollbar.c ================================================================== --- generic/ttk/ttkScrollbar.c +++ generic/ttk/ttkScrollbar.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003 Joe English * * ttk::scrollbar widget. */ #include "tkInt.h" @@ -280,19 +280,20 @@ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(fraction)); return TCL_OK; } static const Ttk_Ensemble ScrollbarCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "delta", ScrollbarDeltaCommand,0 }, { "fraction", ScrollbarFractionCommand,0 }, { "get", ScrollbarGetCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "set", ScrollbarSetCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /*------------------------------------------------------------------------ * +++ Widget specification. Index: generic/ttk/ttkSeparator.c ================================================================== --- generic/ttk/ttkSeparator.c +++ generic/ttk/ttkSeparator.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004 Joe English * * ttk::separator and ttk::sizegrip widgets. */ #include "tkInt.h" @@ -46,15 +46,16 @@ /* * Widget commands: */ static const Ttk_Ensemble SeparatorCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /* * Widget specification: @@ -87,15 +88,16 @@ WIDGET_TAKEFOCUS_FALSE, WIDGET_INHERIT_OPTIONS(ttkCoreOptionSpecs) }; static const Ttk_Ensemble SizegripCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; static const WidgetSpec SizegripWidgetSpec = { Index: generic/ttk/ttkSquare.c ================================================================== --- generic/ttk/ttkSquare.c +++ generic/ttk/ttkSquare.c @@ -1,6 +1,6 @@ -/* square.c - Copyright (C) 2004 Pat Thoyts +/* square.c - Copyright © 2004 Pat Thoyts * * Minimal sample ttk widget. */ #include "tkInt.h" @@ -127,15 +127,16 @@ * subcommands are listed here. Ttk provides default implementations * that are sufficient for our needs. */ static const Ttk_Ensemble SquareCommands[] = { - { "configure", TtkWidgetConfigureCommand,0 }, { "cget", TtkWidgetCgetCommand,0 }, + { "configure", TtkWidgetConfigureCommand,0 }, { "identify", TtkWidgetIdentifyCommand,0 }, { "instate", TtkWidgetInstateCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { 0,0,0 } }; /* * The Widget specification structure holds all the implementation Index: generic/ttk/ttkState.c ================================================================== --- generic/ttk/ttkState.c +++ generic/ttk/ttkState.c @@ -1,9 +1,9 @@ /* * Tk widget state utilities. * - * Copyright (c) 2003 Joe English. Freely redistributable. + * Copyright © 2003 Joe English. Freely redistributable. * */ #include "tkInt.h" #include "ttkTheme.h" Index: generic/ttk/ttkStubLib.c ================================================================== --- generic/ttk/ttkStubLib.c +++ generic/ttk/ttkStubLib.c @@ -32,21 +32,27 @@ MODULE_SCOPE const char * TtkInitializeStubs( Tcl_Interp *interp, const char *version, int epoch, int revision) { int exact = 0; - const char *packageName = "Ttk"; + const char *packageName = "ttk"; const char *errMsg = NULL; void *pkgClientData = NULL; const char *actualVersion = Tcl_PkgRequireEx( interp, packageName, version, exact, &pkgClientData); - const TtkStubs *stubsPtr = (const TtkStubs *)pkgClientData; + const TtkStubs *stubsPtr; if (!actualVersion) { - return NULL; + packageName = "Ttk"; + actualVersion = Tcl_PkgRequireEx( + interp, packageName, version, exact, &pkgClientData); + if (!actualVersion) { + return NULL; + } } + stubsPtr = (const TtkStubs *)pkgClientData; if (!stubsPtr) { errMsg = "missing stub table pointer"; goto error; } if (stubsPtr->epoch != epoch) { Index: generic/ttk/ttkTagSet.c ================================================================== --- generic/ttk/ttkTagSet.c +++ generic/ttk/ttkTagSet.c @@ -1,9 +1,9 @@ /* * Tag tables. 3/4-baked, work in progress. * - * Copyright (C) 2005, Joe English. Freely redistributable. + * Copyright © 2005, Joe English. Freely redistributable. */ #include "tkInt.h" #include "ttkTheme.h" #include "ttkWidget.h" Index: generic/ttk/ttkTheme.c ================================================================== --- generic/ttk/ttkTheme.c +++ generic/ttk/ttkTheme.c @@ -1,12 +1,12 @@ /* * ttkTheme.c -- * * This file implements the widget styles and themes support. * - * Copyright (c) 2002 Frederic Bonnet - * Copyright (c) 2003 Joe English + * Copyright © 2002 Frederic Bonnet + * Copyright © 2003 Joe English * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -93,11 +93,11 @@ return 0; } /* * Ttk_StyleDefault -- - * Look up default resource setting the in the specified style. + * Look up default resource setting in the specified style. */ Tcl_Obj *Ttk_StyleDefault(Ttk_Style style, const char *optionName) { while (style) { Tcl_HashEntry *entryPtr = @@ -1260,14 +1260,14 @@ } styleName = Tcl_GetString(objv[2]); stylePtr = Ttk_GetStyle(theme, styleName); - if (objc == 3) { /* style default $styleName */ + if (objc == 3) { /* style configure $styleName */ Tcl_SetObjResult(interp, HashTableToDict(&stylePtr->defaultsTable)); return TCL_OK; - } else if (objc == 4) { /* style default $styleName -option */ + } else if (objc == 4) { /* style configure $styleName -option */ const char *optionName = Tcl_GetString(objv[3]); Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&stylePtr->defaultsTable, optionName); if (entryPtr) { Tcl_SetObjResult(interp, (Tcl_Obj*)Tcl_GetHashValue(entryPtr)); @@ -1313,13 +1313,11 @@ Tcl_WrongNumArgs(interp, 2, objv, "style -option ?state? ?default?"); return TCL_ERROR; } style = Ttk_GetStyle(theme, Tcl_GetString(objv[2])); - if (!style) { - return TCL_ERROR; - } + optionName = Tcl_GetString(objv[3]); if (objc >= 5) { Ttk_StateSpec stateSpec; /* @@@ SB: Ttk_GetStateFromObj(); 'offbits' spec is ignored */ @@ -1609,10 +1607,35 @@ Ttk_RegisterLayoutTemplate(theme, layoutName, layoutTemplate); ThemeChanged(pkgPtr); } return TCL_OK; } + +/* + style theme styles ?$theme? -- + * Return list of styles available in $theme. + * Use the current theme if $theme is omitted. + */ +static int StyleThemeStylesCmd( + TCL_UNUSED(ClientData), Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + Ttk_Theme themePtr; + + if (objc < 3 || objc > 4) { + Tcl_WrongNumArgs(interp, 3, objv, "?theme?"); + return TCL_ERROR; + } + + if (objc == 3) { + themePtr = Ttk_GetCurrentTheme(interp); + } else { + themePtr = Ttk_GetTheme(interp, Tcl_GetString(objv[3])); + } + if (!themePtr) + return TCL_ERROR; + + return TtkEnumerateHashTable(interp, &themePtr->styleTable); +} /* + style theme use $theme -- * Sets the current theme to $theme */ static int @@ -1649,10 +1672,11 @@ static const Ttk_Ensemble StyleThemeEnsemble[] = { { "create", StyleThemeCreateCmd, 0 }, { "names", StyleThemeNamesCmd, 0 }, { "settings", StyleThemeSettingsCmd, 0 }, + { "styles", StyleThemeStylesCmd, 0 }, { "use", StyleThemeUseCmd, 0 }, { NULL, 0, 0 } }; static const Ttk_Ensemble StyleElementEnsemble[] = { Index: generic/ttk/ttkTrack.c ================================================================== --- generic/ttk/ttkTrack.c +++ generic/ttk/ttkTrack.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004, Joe English * * TtkTrackElementState() -- helper routine for widgets * like scrollbars in which individual elements may * be active or pressed instead of the widget as a whole. * Index: generic/ttk/ttkTreeview.c ================================================================== --- generic/ttk/ttkTreeview.c +++ generic/ttk/ttkTreeview.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 2004, Joe English + * Copyright © 2004, Joe English * * ttk::treeview widget implementation. */ #include "tkInt.h" @@ -3293,21 +3293,22 @@ { "exists", TreeviewExistsCommand,0 }, { "focus", TreeviewFocusCommand,0 }, { "heading", TreeviewHeadingCommand,0 }, { "identify", TreeviewIdentifyCommand,0 }, { "index", TreeviewIndexCommand,0 }, - { "instate", TtkWidgetInstateCommand,0 }, { "insert", TreeviewInsertCommand,0 }, + { "instate", TtkWidgetInstateCommand,0 }, { "item", TreeviewItemCommand,0 }, { "move", TreeviewMoveCommand,0 }, { "next", TreeviewNextCommand,0 }, { "parent", TreeviewParentCommand,0 }, { "prev", TreeviewPrevCommand,0 }, { "see", TreeviewSeeCommand,0 }, { "selection" , TreeviewSelectionCommand,0 }, { "set", TreeviewSetCommand,0 }, { "state", TtkWidgetStateCommand,0 }, + { "style", TtkWidgetStyleCommand,0 }, { "tag", 0,TreeviewTagCommands }, { "xview", TreeviewXViewCommand,0 }, { "yview", TreeviewYViewCommand,0 }, { 0,0,0 } }; Index: generic/ttk/ttkWidget.c ================================================================== --- generic/ttk/ttkWidget.c +++ generic/ttk/ttkWidget.c @@ -1,19 +1,15 @@ /* - * Copyright (c) 2003, Joe English + * Copyright © 2003, Joe English * * Core widget utilities. */ #include "tkInt.h" -#include "ttkTheme.h" +#include "ttkThemeInt.h" #include "ttkWidget.h" -#ifdef MAC_OSX_TK -#define TK_NO_DOUBLE_BUFFERING 1 -#endif - /*------------------------------------------------------------------------ * +++ Internal helper routines. */ /* UpdateLayout -- @@ -792,9 +788,29 @@ if (element) { const char *elementName = Ttk_ElementName(element); Tcl_SetObjResult(interp,Tcl_NewStringObj(elementName,-1)); } + return TCL_OK; +} + +/* $w style + * Return the style currently applied to the widget. + */ + +int TtkWidgetStyleCommand( + void *recordPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) +{ + WidgetCore *corePtr = (WidgetCore *)recordPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + + Tcl_SetObjResult(interp, Tcl_NewStringObj( + Ttk_StyleName(Ttk_LayoutStyle(corePtr->layout)), -1)); + return TCL_OK; } /*EOF*/ Index: generic/ttk/ttkWidget.h ================================================================== --- generic/ttk/ttkWidget.h +++ generic/ttk/ttkWidget.h @@ -87,19 +87,21 @@ MODULE_SCOPE int TtkCoreConfigure(Tcl_Interp*, void *, int mask); /* Common widget commands: */ +MODULE_SCOPE int TtkWidgetCgetCommand( + void *,Tcl_Interp *, int, Tcl_Obj*const[]); MODULE_SCOPE int TtkWidgetConfigureCommand( void *,Tcl_Interp *, int, Tcl_Obj*const[]); -MODULE_SCOPE int TtkWidgetCgetCommand( +MODULE_SCOPE int TtkWidgetIdentifyCommand( void *,Tcl_Interp *, int, Tcl_Obj*const[]); MODULE_SCOPE int TtkWidgetInstateCommand( void *,Tcl_Interp *, int, Tcl_Obj*const[]); MODULE_SCOPE int TtkWidgetStateCommand( void *,Tcl_Interp *, int, Tcl_Obj*const[]); -MODULE_SCOPE int TtkWidgetIdentifyCommand( +MODULE_SCOPE int TtkWidgetStyleCommand( void *,Tcl_Interp *, int, Tcl_Obj*const[]); /* Widget constructor: */ MODULE_SCOPE int TtkWidgetConstructorObjCmd( Index: library/bgerror.tcl ================================================================== --- library/bgerror.tcl +++ library/bgerror.tcl @@ -4,12 +4,12 @@ # the error message and gives the user a chance to see a more detailed # stack trace, and possible do something more interesting with that # trace (like save it to a log). This is adapted from work done by # Donal K. Fellows. # -# Copyright © 1998-2000 by Ajuba Solutions. -# Copyright © 2007 by ActiveState Software Inc. +# Copyright © 1998-2000 Ajuba Solutions. +# Copyright © 2007 ActiveState Software Inc. # Copyright © 2007 Daniel A. Steffen # Copyright © 2009 Pat Thoyts namespace eval ::tk::dialog::error { namespace import -force ::tk::msgcat::* Index: library/button.tcl ================================================================== --- library/button.tcl +++ library/button.tcl @@ -39,14 +39,14 @@ bind Checkbutton { tk::ButtonLeave %W } } if {"win32" eq [tk windowingsystem]} { - bind Checkbutton { + bind Checkbutton <=> { tk::CheckRadioInvoke %W select } - bind Checkbutton { + bind Checkbutton <+> { tk::CheckRadioInvoke %W select } bind Checkbutton { tk::CheckRadioInvoke %W deselect } Index: library/choosedir.tcl ================================================================== --- library/choosedir.tcl +++ library/choosedir.tcl @@ -1,10 +1,10 @@ # choosedir.tcl -- # # Choose directory dialog implementation for Unix/Mac. # -# Copyright © 1998-2000 by Scriptics Corporation. +# Copyright © 1998-2000 Scriptics Corporation. # All rights reserved. # Make sure the tk::dialog namespace, in which all dialogs should live, exists namespace eval ::tk::dialog {} namespace eval ::tk::dialog::file {} Index: library/comdlg.tcl ================================================================== --- library/comdlg.tcl +++ library/comdlg.tcl @@ -27,11 +27,12 @@ # specs = { # {-commandlineswitch resourceName ResourceClass defaultValue verifier} # {....} # } # -# flags = currently unused. +# flags = a list of flags. Currently supported flags are: +# DONTSETDEFAULTS = skip default values setting # # argList = The list of "-option value" pairs. # proc tclParseConfigSpec {w specs flags argList} { upvar #0 $w data @@ -61,12 +62,14 @@ "value for \"$cmdsw\" missing" } # 2: set the default values # - foreach cmdsw [array names cmd] { - set data($cmdsw) $def($cmdsw) + if {"DONTSETDEFAULTS" ni $flags} { + foreach cmdsw [array names cmd] { + set data($cmdsw) $def($cmdsw) + } } # 3: parse the argument list # foreach {cmdsw value} $argList { Index: library/console.tcl ================================================================== --- library/console.tcl +++ library/console.tcl @@ -452,27 +452,20 @@ <> <> <> <> <> - <> + <> <> + <> + <> } { event add $ev $key bind Console $key {} } - if {[tk windowingsystem] eq "aqua"} { - foreach {ev key} { - <> - <> - } { - event add $ev $key - bind Console $key {} - } - if {$::tk::console::useFontchooser} { - bind Console [list ::tk::console::FontchooserToggle] - } + if {$::tk::console::useFontchooser} { + bind Console [list ::tk::console::FontchooserToggle] } bind Console <> { if {[%W compare insert > promptEnd]} { ::tk::console::Expand %W } @@ -592,14 +585,12 @@ } bind Console { eval destroy [winfo child .] source -encoding utf-8 [file join $tk_library console.tcl] } - if {[tk windowingsystem] eq "aqua"} { - bind Console { - exit - } + bind Console { + exit } bind Console <> { ::tk::console::Cut %W } bind Console <> { ::tk::console::Copy %W } bind Console <> { ::tk::console::Paste %W } Index: library/demos/cscroll.tcl ================================================================== --- library/demos/cscroll.tcl +++ library/demos/cscroll.tcl @@ -112,11 +112,11 @@ if {[tk windowingsystem] eq "x11" && ![package vsatisfies [package provide Tk] 8.7-]} { # Support for mousewheels on Linux/Unix commonly comes through mapping # the wheel to the extended buttons. If you have a mousewheel, find # Linux configuration info at: - # http://linuxreviews.org/howtos/xfree/mouse/ + # https://linuxreviews.org/HOWTO_change_the_mouse_speed_in_X bind $c { if {!$tk_strictMotif} { %W yview scroll -5 units } } Index: library/demos/entry3.tcl ================================================================== --- library/demos/entry3.tcl +++ library/demos/entry3.tcl @@ -62,17 +62,17 @@ } labelframe $w.l1 -text "Integer Entry" # Alternatively try using {string is digit} for arbitrary length numbers, # and not just 32-bit ones. -entry $w.l1.e -validate focus -vcmd {string is integer %P} +entry $w.l1.e -validate focus -validatecommand {string is integer %P} $w.l1.e configure -invalidcommand \ "focusAndFlash %W [$w.l1.e cget -fg] [$w.l1.e cget -bg]" pack $w.l1.e -fill x -expand 1 -padx 1m -pady 1m labelframe $w.l2 -text "Length-Constrained Entry" -entry $w.l2.e -validate key -invcmd bell -vcmd {expr {[string length %P]<10}} +entry $w.l2.e -validate key -invcmd bell -validatecommand {expr {[string length %P]<10}} pack $w.l2.e -fill x -expand 1 -padx 1m -pady 1m ### PHONE NUMBER ENTRY ### # Note that the source to this is quite a bit longer as the behaviour # demonstrated is a lot more ambitious than with the others. @@ -159,11 +159,11 @@ } } labelframe $w.l3 -text "US Phone-Number Entry" entry $w.l3.e -validate key -invcmd bell -textvariable entry3content \ - -vcmd {validatePhoneChange %W %v %i %S} + -validatecommand {validatePhoneChange %W %v %i %S} # Click to focus goes to the first editable character... bind $w.l3.e { if {"%d" ne "NotifyAncestor"} { %W icursor 3 after idle {%W selection clear} @@ -172,14 +172,14 @@ bind $w.l3.e <> {phoneSkipLeft %W} bind $w.l3.e <> {phoneSkipRight %W} pack $w.l3.e -fill x -expand 1 -padx 1m -pady 1m labelframe $w.l4 -text "Password Entry" -entry $w.l4.e -validate key -show "*" -vcmd {expr {[string length %P]<=8}} +entry $w.l4.e -validate key -show "*" -validatecommand {expr {[string length %P]<=8}} pack $w.l4.e -fill x -expand 1 -padx 1m -pady 1m lower [frame $w.mid] grid $w.l1 $w.l2 -in $w.mid -padx 3m -pady 1m -sticky ew grid $w.l3 $w.l4 -in $w.mid -padx 3m -pady 1m -sticky ew grid columnconfigure $w.mid {0 1} -uniform 1 pack $w.msg -side top pack $w.mid -fill both -expand 1 Index: library/demos/menu.tcl ================================================================== --- library/demos/menu.tcl +++ library/demos/menu.tcl @@ -61,11 +61,11 @@ } else { set modifier Meta } foreach i {A B C D E F} { $m add command -label "Print letter \"$i\"" -underline 14 \ - -accelerator Meta+$i -command "puts $i" -accelerator $modifier+$i + -accelerator $modifier+$i -command "puts $i" bind $w <$modifier-[string tolower $i]> "puts $i" } set m $w.menu.cascade $w.menu add cascade -label "Cascades" -menu $m -underline 0 @@ -132,10 +132,12 @@ $w.menu add cascade -label "More" -menu $m -underline 0 menu $m -tearoff 0 foreach i {{An entry} {Another entry} {Does nothing} {Does almost nothing} {Does almost nothing also} {Make life meaningful}} { $m add command -label $i -command [list puts "You invoked \"$i\""] } +set emojiLabel [encoding convertfrom utf-8 "\xF0\x9F\x98\x8D Make friends"] +$m add command -label $emojiLabel -command [list puts "Menu labels can include non-BMP characters."] $m entryconfigure "Does almost nothing" -bitmap questhead -compound left \ -command [list \ tk_dialog $w.compound {Compound Menu Entry} \ "The menu entry you invoked displays both a bitmap and a\ text string. Other than this, it is just like any other\ @@ -149,13 +151,28 @@ menu entry." {} 0 OK ] set m $w.menu.colors $w.menu add cascade -label "Colors" -menu $m -underline 1 menu $m -tearoff 1 -foreach i {red orange yellow green blue} { - $m add command -label $i -background $i -command [list \ - puts "You invoked \"$i\"" ] +if {[tk windowingsystem] eq "aqua"} { + # Aqua ignores the -background and -foreground options, but a compound + # button can be used for selecting colors. + foreach i {red orange yellow green blue} { + image create photo image_$i -height 16 -width 16 + image_$i put black -to 0 0 16 1 + image_$i put black -to 0 1 1 16 + image_$i put black -to 0 15 16 16 + image_$i put black -to 15 1 16 16 + image_$i put $i -to 1 1 15 15 + $m add command -label $i -image image_$i -compound left -command [list \ + puts "You invoked \"$i\"" ] + } +} else { + foreach i {red orange yellow green blue} { + $m add command -label $i -background $i -command [list \ + puts "You invoked \"$i\"" ] + } } $w configure -menu $w.menu bind Menu <> { ADDED library/demos/print.tcl Index: library/demos/print.tcl ================================================================== --- /dev/null +++ library/demos/print.tcl @@ -0,0 +1,53 @@ +# print.tcl -- +# +# This demonstration script showcases the tk print commands. +# + +if {![info exists widgetDemo]} { + error "This script should be run from the \"widget\" demo." +} + +set w .print +destroy $w +toplevel $w +wm title $w "Printing Demonstration" +positionWindow $w + +image create photo logo -data {R0lGODlhMABLAPUAAP//////zP//mf//AP/MzP/Mmf/MAP+Zmf+ZZv+ZAMz//8zM/8zMzMyZzMyZmcyZZsyZAMxmZsxmM8xmAMwzM8wzAJnMzJmZzJmZmZlmmZlmZplmM5kzZpkzM5kzAGaZzGZmzGZmmWYzZmYzMzNmzDNmmTMzmTMzZgAzmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+BSAtZGwtACH5BAEKAAIALAAAAAAwAEsAAAb+QIFwSCwahY9HRMI8Op/JJVNSqVqv2OvjyRU8slbIJGwYg60S5ZR6jRi/4ITBOhkYIOd8dltEnAdmFQMJeoVXCEd/VnKGjRVOZ3NVgHlsjpBxVRCEYBIEAAARl4lgZmVgEQAKFx8Mo0ZnpqgAFyi2JqKGmGebWRIAILbCIo27cYFWASTCtievRXqSVwQfzLYeeYESxlnSVRIW1igjWHJmjBXbpKXeFQTizlh1eJNVHbYf0LGc39XW2PIoVZE0whasWPSqFBBHrkKEA3QG0DFTEMXBUsjCWesg4oMFAGwgtKsiwqA+jGiCiRPGAM6pLCVLGKHQ6EGJlc0IuDxzAgX+CCOW9DjAaUsEyAoT+GHpeSRoHgxEUWgAUEUpFhMWgTbKEPUBAU15TBZxekYD0RMEqCDLIpYIWTAcmGEd9rWQBxQyjeQqdK/ZTWEO3mK5l+9No75SrcHhm9WwnlzNoA5zdM+JHz0HCPQdUauZowoFnSw+c2CBvw6dUXT4LMKE6EIHUqMexgCiIREknOwl7Q+FhNQoLuzOc6Kw3kIIVOLqjYKBYCwinmgo9CBEswfMAziK7mRDoQhcUZxwoBKFibq3n3jXI0GyCPLC0DrS8GR1oaEoRBRYVhT99/qG4DcCA/yNU4Ajbjhhnx4P2DJggR3YZog6RyyYxwM9PSgMBaP+sQdgIRL0JAKBwnTooRMAFWLdiPyJ8JwvTnyQoh5midCASh149ZkTIFAmHnzOZOBfIU6U4Mhd4zF34DNEoDAhARGY50BvJkioyxFOGkKAShGkFsJwejiR5Xf8aZAaBp89coQJjuDXAQOApekEm45ANaAtIbyYxREf0OlICCK841uaahZBQjyfjXCACYjuaASjhFagRKSFNtloHg+hYWIxRohnBQWCSSAhBVZ+hkgRnlbxwJIVgIqGlaU6wkeTxHxjm6gVLImrFbHWVEQ1taZjWxJX7KqqnqgUEUxDwtqajrOaRkqhEDcxWwECbEjxTYe9gojqOJQ6JO231ob72bSqAjh4RgfsjiDCCfDCK8K8I9TL7r33nvGtCO7CO1dUAONk3LcBFxzwwEMwZ/DC4iAsRIE+CWNCbzeV8FfEtoDwVwnlacxMkcKQYIE/F5TQ2QcedUZCagyc3NsFGrXVZMipWVBCzKv4Q0JvCviDsjAwf4ylxBeX0KcwGs81ccgqGS3MBxc3RjDDVAvdBRcfeFy1MFd3bcQHJEQdlddkP5E1Cf9yXfbaV2d9RBAAOw== +} + + +pack [label $w.l -text "This demonstration showcases + the tk print command. Clicking the buttons below + print the data from the canvas and text widgets + using platform-native dialogs."] -side top + +pack [frame $w.m] -fill both -expand yes -side top + +set c [canvas $w.m.c -bg white] +pack $c -fill both -expand no -side left + +$c create rectangle 30 10 200 50 -fill blue -outline black +$c create oval 30 60 200 110 -fill green +$c create image 130 150 -image logo +$c create text 150 250 -anchor n -font {Helvetica 12} \ + -text "A short demo of simple canvas elements." + +set txt { +Tcl, 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. + +Tcl 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. +} + +set t [text $w.m.t -wrap word] +pack $t -side right -fill both -expand no +$t insert end $txt + +pack [frame $w.f] -side top -fill both -expand no +pack [button $w.f.b -text "Print Canvas" -command [list tk print $w.m.c]] -expand no +pack [button $w.f.x -text "Print Text" -command [list tk print $w.m.t]] -expand no + +## See Code / Dismiss buttons +pack [addSeeDismiss $w.buttons $w] -side bottom -fill x + + Index: library/demos/spin.tcl ================================================================== --- library/demos/spin.tcl +++ library/demos/spin.tcl @@ -36,11 +36,11 @@ Canberra Sydney Melbourne Perth Adelaide Brisbane Hobart Darwin "Alice Springs" } spinbox $w.s1 -from 1 -to 10 -width 10 -validate key \ - -vcmd {string is integer %P} + -validatecommand {string is integer %P} spinbox $w.s2 -from 0 -to 3 -increment .5 -format %05.2f -width 10 spinbox $w.s3 -values $australianCities -width 10 #entry $w.e1 #entry $w.e2 Index: library/demos/square ================================================================== --- library/demos/square +++ library/demos/square @@ -9,12 +9,12 @@ # bindings for the widget: # # Button-1 press/drag: moves square to mouse # "a": toggle size animation on/off -package require Tk ;# We use Tk generally, and... -package require Tktest ;# ... we use the square widget too. +package require tk ;# We use Tk generally, and... +package require tk::test ;# ... we use the square widget too. square .s pack .s -expand yes -fill both wm minsize . 1 1 ADDED library/demos/systray.tcl Index: library/demos/systray.tcl ================================================================== --- /dev/null +++ library/demos/systray.tcl @@ -0,0 +1,89 @@ +# systray.tcl -- +# +# This demonstration script showcases the tk systray and tk sysnotify commands. +# + +if {![info exists widgetDemo]} { + error "This script should be run from the \"widget\" demo." +} + +set w .systray +destroy $w +toplevel $w +wm title $w "System Tray Demonstration" +positionWindow $w + +catch {tk systray destroy} +set trayIconExists false + +set iconmenu .menubar +destroy $iconmenu +menu $iconmenu +$iconmenu add command -label "Status" -command { puts "status icon clicked" } +$iconmenu add command -label "Exit" -command exit + +pack [label $w.l -text "This demonstration showcases + the tk systray and tk sysnotify commands. + Running this demo creates the systray icon. + Clicking the buttons below modifies and destroys the icon + and displays the notification."] + +image create photo book -data R0lGODlhDwAPAKIAAP//////AP8AAMDAwICAgAAAAAAAAAAAACwAAAAADwAPAAADSQhA2u5ksPeKABKSCaya29d4WKgERFF0l1IMQCAKatvBJ0OTdzzXI1xMB3TBZAvATtB6NSLKleXi3OBoLqrVgc0yv+DVSEUuFxIAOw== + +labelframe $w.f -text "Tray Icon" +button $w.f.b0 -text "Create" -command create +button $w.f.b1 -text "Modify" -command modify +button $w.f.b2 -text "Destroy" -command remove +pack $w.f.b0 $w.f.b1 $w.f.b2 -padx 5 -pady 3 -side left -expand true -fill x + +button $w.b3 -text "Display Notification" -command notify +pack $w.f $w.b3 -expand true -fill x -padx 5 -pady 5 + +proc create {} { + global trayIconExists + if {$trayIconExists} { + tk_messageBox -message "Systray icon already exists" + return + } + tk systray create -image book -text "Systray sample" \ + -button1 {puts "foo"} \ + -button3 {tk_popup $iconmenu [winfo pointerx .] [winfo pointery .]} + set trayIconExists true +} + +proc modify {} { + global trayIconExists + if {!$trayIconExists} { + tk_messageBox -message "Please create systray icon first" + return + } + image create photo page -data R0lGODlhCwAPAKIAAP//////AMDAwICAgAAA/wAAAAAAAAAAACwAAAAACwAPAAADMzi6CzAugiAgDGE68aB0RXgRJBFVX0SNpQlUWfahQOvSsgrX7eZJMlQMWBEYj8iQchlKAAA7 + tk systray configure -image page + tk systray configure -text "Modified text" + tk systray configure -button1 {puts "this is a different output"} + tk systray configure -button3 {puts "hello yall"} +} + +proc notify {} { + global trayIconExists + if {!$trayIconExists} { + tk_messageBox -message "Please create systray icon first" + return + } + tk sysnotify "Alert" "This is an alert" +} + +proc remove {} { + global trayIconExists + if {!$trayIconExists} { + tk_messageBox -message "Systray icon was already destroyed" + return + } + tk systray destroy + set trayIconExists false +} + +create + +## See Code / Dismiss buttons +pack [addSeeDismiss $w.buttons $w] -side bottom -fill x Index: library/demos/tclIndex ================================================================== --- library/demos/tclIndex +++ library/demos/tclIndex @@ -63,5 +63,8 @@ set auto_index(setHeight) [list source -encoding utf-8 [file join $dir vscale.tcl]] set auto_index(showMessageBox) [list source -encoding utf-8 [file join $dir msgbox.tcl]] set auto_index(setColor) [list source -encoding utf-8 [file join $dir clrpick.tcl]] set auto_index(setColor_helper) [list source -encoding utf-8 [file join $dir clrpick.tcl]] set auto_index(fileDialog) [list source -encoding utf-8 [file join $dir filebox.tcl]] +set auto_index(systray) [list source -encoding utf-8 [file join $dir systray.tcl]] +set auto_index(windoicons [list source -encoding utf-8 [file join $dir windowicons.tcl]] + Index: library/demos/widget ================================================================== --- library/demos/widget +++ library/demos/widget @@ -364,11 +364,10 @@ @@demo knightstour A Knight's tour of the chess board @@subtitle Scales and Progress Bars @@demo hscale Horizontal scale @@demo vscale Vertical scale - @@new @@demo ttkscale Themed scale linked to a label with traces @@demo ttkprogress Progress bar @@subtitle Paned Windows and Notebooks @@demo paned1 Horizontal paned window @@ -385,10 +384,14 @@ @@subtitle Common Dialogs @@demo msgbox Message boxes @@demo filebox File selection dialog @@demo clrpick Color picker @@demo fontchoose Font selection dialog + @@new + @@demo systray System tray icon and notification + @@new + @@demo print Printing from canvas and text widgets @@subtitle Animation @@demo anilabel Animated labels @@demo aniwave Animated wave @@demo pendulum Pendulum simulation @@ -396,10 +399,12 @@ @@subtitle Miscellaneous @@demo bitmap The built-in bitmaps @@demo dialog1 A dialog box with a local grab @@demo dialog2 A dialog box with a global grab + @@new + @@demo windowicons Window icons and badges } ############################################################################## .t configure -state disabled @@ -622,11 +627,11 @@ raise $top } wm title $top [mc "Demo code: %s" [file join $tk_demoDirectory $file]] wm iconname $top $file set id [open [file join $tk_demoDirectory $file]] - fconfigure $id -encoding utf-8 -eofchar \032 + fconfigure $id -encoding utf-8 -eofchar "\032 {}" $top.f.text delete 1.0 end $top.f.text insert 1.0 [read $id] $top.f.text mark set insert 1.0 close $id } @@ -638,84 +643,11 @@ # Arguments: # w - Name of text widget containing code to print # file - Name of the original file (implicitly for title) proc printCode {w file} { - set code [$w get 1.0 end-1c] - - set dir "." - if {[info exists ::env(HOME)]} { - set dir "$::env(HOME)" - } - if {[info exists ::env(TMP)]} { - set dir $::env(TMP) - } - if {[info exists ::env(TEMP)]} { - set dir $::env(TEMP) - } - - set filename [file join $dir "tkdemo-$file"] - set outfile [open $filename "w"] - puts $outfile $code - close $outfile - - switch -- $::tcl_platform(platform) { - unix { - if {[catch {exec lp -c $filename} msg]} { - tk_messageBox -title "Print spooling failure" \ - -message "Print spooling probably failed: $msg" - } - } - windows { - if {[catch {PrintTextWin32 $filename} msg]} { - tk_messageBox -title "Print spooling failure" \ - -message "Print spooling probably failed: $msg" - } - } - default { - tk_messageBox -title "Operation not Implemented" \ - -message "Wow! Unknown platform: $::tcl_platform(platform)" - } - } - - # - # Be careful to throw away the temporary file in a gentle manner ... - # - if {[file exists $filename]} { - catch {file delete $filename} - } -} - -# PrintTextWin32 -- -# Print a file under Windows using all the "intelligence" necessary -# -# Arguments: -# filename - Name of the file -# -# Note: -# Taken from the Wiki page by Keith Vetter, "Printing text files under -# Windows". -# Note: -# Do not execute the command in the background: that way we can dispose of the -# file smoothly. -# -proc PrintTextWin32 {filename} { - package require registry - set app [auto_execok notepad.exe] - set pcmd "$app /p %1" - catch { - set app [registry get {HKEY_CLASSES_ROOT\.txt} {}] - set pcmd [registry get \ - {HKEY_CLASSES_ROOT\\$app\\shell\\print\\command} {}] - } - - regsub -all {%1} $pcmd $filename pcmd - puts $pcmd - - regsub -all {\\} $pcmd {\\\\} pcmd - set command "[auto_execok start] /min $pcmd" - eval exec $command + tk print $w } # tkAboutDialog -- # # Pops up a message box with an "about" message @@ -724,11 +656,12 @@ tk_messageBox -icon info -type ok -title [mc "About Widget Demo"] \ -message [mc "Tk widget demonstration application"] -detail \ "[mc "Copyright © %s" {1996-1997 Sun Microsystems, Inc.}] [mc "Copyright © %s" {1997-2000 Ajuba Solutions, Inc.}] [mc "Copyright © %s" {2001-2009 Donal K. Fellows}] -[mc "Copyright © %s" {2002-2007 Daniel A. Steffen}]" +[mc "Copyright © %s" {2002-2007 Daniel A. Steffen}] +[mc "Copyright © %s" {2021 Kevin Walzer}]" } # Local Variables: # mode: tcl # End: ADDED library/demos/windowicons.tcl Index: library/demos/windowicons.tcl ================================================================== --- /dev/null +++ library/demos/windowicons.tcl @@ -0,0 +1,99 @@ +# windowicons.tcl -- +# +# This demonstration script showcases the wm iconphoto and wm iconbadge commands. +# + +if {![info exists widgetDemo]} { + error "This script should be run from the \"widget\" demo." +} + +set w .windowicons +destroy $w +toplevel $w +wm title $w "Window Icon Demonstration" +positionWindow $w + +image create photo icon -data { + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGP + C/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3Cc + ulE8AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAArQNAAK0DQEdFIm+AAAJ + QElEQVRYw+WXW2xdV5nHf/ty7lcf2/FxYsdOnMSNC0HTpDiRKJWAQjWCEQNU + SEAFfUOiQqrEC2+IxwpemDLSzNBBCCQeQEKqRJgBSikiuGlN22TqhsR27OPL + 8eWc43Pdt7X22osHHydOm4FBPM6Slr69paX9/32Xtb614f/7MP6vC3O5f8L3 + G7HJyZPHBwfz5wrF7HQ6nRwxLTOhQuU4PW+z3eq9Xa+33rq9cms7k8pHjvfS + 3w8wOfk52u1u8oHpiUff897JJ8+dO/nI6LHho6OjQ3ahkMYwTTZ2O2zXutS3 + G/7ayubq7Vtr/7Ve2f7RytLam4ViXq1t/vRvB0ilPsjzz3+LZ5/9j7MzM5Nf + /8hj5//5H97/YNbK5hkfTFLMxAEQQvD766v0yBGIEBEEuPUGi9dv7lx77cb3 + Vm9vfqc0WNi9evUKWr/xLh3rfuLj45+l0bjM7m768U98/OJ/fulLH/3wiemx + eCafxRcKw7TJxKC+12RpbYdAx7HsOCrSRNpg+sQQj1w8nS0N5h8JAvm+rWr9 + 9ZmZB2qWdZq9vWt/GWBm5im+9rUn6HRGPv7EE4/++2P/eOFkV0FkJTDQgCaX + TbO1tcV2R2EmCxBJQixs2+R9EwV00MFAceJE2ZiZOT7VaTsPLyxU5orFTK1c + fphq9bX7A8zOfoV8Ps3c3NsXPvWpD37vc5//0ETNt8gNjDAzlsdAE0vliTCR + xEhnC2CaRIZNMmZiaonv9mh1PcrDJQZzCfK5OGNjQ8e2tvZO37y5+ctk0naq + 1fn7A4yOnmd5uVp4/PGHn/vylz8xe+zoEIP5JAMpA0OHeK6DG4TEk2li8Tha + QxRpIg0q6DGUNjg6UuLYSInhYoYoigiCgHQ6TrGYnlpd3Q1ffvk3L128+ITe + 2Hj1XoBLl55menqcbDb1haeeevyrDz102tJaE7ctLBMqG1X23Ag7kcKOJzAA + DSilCVWEZdmMDaXJJCxSiRimaaK1RkqJ7/uUSlk6Hed0oxG9HI9bm+Pjs2xs + vIp5AKC15oUX/lA8f/7MF2dnz8YADMNASslypYqrUxSHyqSy+f31hzaRZRpM + DKVYr+7y4usVri1WWavWCWSIZZkYhoFSIRcuTI1MTAw9OTf33Tu7zz54SCRi + nD17/Pzs7AMPFQqZPlTE8vo2DlmGhgbo12BffD/8SmukitiuNxHKoDwyzPJG + nTdXmtiWwdnRNCN5GxWGDA/nOH26/NGpqSfHgPU7AJcuPc0nP/kBrl698YGZ + mYmMEIJmx6Hn+my0DUZGC6gIzEOnhu4Lh2GEbRocGyxRSO/7c3QgiRuEVOtd + EvEQrSN8IVEq5MSJ4YlSKX3OMKJ14G4KnnnmM9bkZPk92VyKy3M3eentJjd3 + FUYyjxuEeELt7/NoP+eBVAipCFXEsYE4xcydYFIeSHKynOXhUwM0mh32egH1 + tsdL16oo007kcskHs7kYly49fRcALqby+fQopklkZ4jHY3g6gQgjHF/QcgQd + V+7DHJoGmnzSQuvD0QGlIsJQkU4luLXR4kgxxcRgjM1mQCyZHrv0sUe4JwKF + XMmu7/VSXV9xaXqI0YzC8328QOJ4gq4raHQDGt2AtitwfIEbSAwibOvdJ7pS + CiElR3IxGh2X5Y0GV66v0wnAsq3MN5759L1FqKMoCkQoX19u0QkkD47lKSYi + Th1NoSLYafu0ehrTNNBaE2mNUop2z+DEUJKBbPxecSEIgoAoUjwwmmZpdZPl + muL4oIFWkbx8rXIvQMfZ9p2e1xBCstOJcFe6nB1NcWokhW1ZHMkazK90qXXD + fZFII0NFIBW/XQiZHraoNbsU81mmjhbxfZ8gCAiCgELKQitJGCoIQ6SQO//2 + ze/fm4Kf/Px50dzr3Aoch1Ap2o4kn8tgW/sHynAxzcVTBQYzFp4v6boBjidw + fcFCpcmPf7/Oz+ZrvPBalb12D9/370DUGk1evr6NacWIfD/yveDmXq3F3Nxz + dwH+5dkfUq8155rb9dA2QcqQcjFx57DRGgaySR47d4RHZ0pYeh/C9QSOJ3EE + CGWw3fJZ323j+x6e5xH4Pgu3d6g0FMWUjdvu7bo9/5oK1d0IzM09hwhCGrvN + ubXFylI2pum4AZXtDqEURFGE1hoNxGMW5ZyB22nS8wQ9r1+QvsDzBc1uQGW7 + jee6eN4+RMfxMdHkYgatWmtur9ZaOnD8TgQMA27c+uH68s3KT8O9BoYBv3pj + kxuVGo7Tw+1/MAh83lreYm1P9r3fT4XjSVxf4voC1/NwHAfXdXFcB891KGVj + hO2e16q3fzR2cjQwDPPeZrSx8SqXL2/RqDU2EnH7I8dPjQ8v7Tqs1RwmSzEs + QoQQSBHw1lKVha0AEUb4IiQQIb4I8YUkkCHTQwa5WIjne9xY2mT+VouRfI7N + xfVfrK8sfTuRSAavXP3Xd7fjavWPRq1+3TeiQTVcGnh0oHwktlZzmBq0SNsR + QgiuXLvNL/+nQU/aBFL1xSW+kAghEb5PEkE5q3Bdl7dv72LGCrTXdzf+9Nb8 + N5dXfrG6Wf1jeNDP3nkjigOFWm2xpvx0+tjI8LnMYMnMxQT5eIjruVye36LS + TRAqRSD3vZdCIqUgEj5R4CEDj2O5kMZei3rHoLXV6Sy88cp3Fhf/ew6IAAGE + 9wOIARmtw9Tu7vKa1yY+Wiqeee+ZYdsi4HdvrjK/HiKUiZQhoZREQhDJAC18 + tPSIhEfouwSuQ9cx2VxpNK/PX/n+4uKvXwQdAAHgA/J+AAaQABJRJOydnVsr + zZ1O13eMcSuezC61LJzQRgY+KvCJhI+WPpH0IAywIkEhaVIupAhdHS0t3F66 + Nv/iD9bW/nAFtAM4QA9wAXX3RnEvQBoYODSL+fzEmalTsx+emjl3YWjsaMlM + pcwg0ggZEimFoSNsI8JSCtF1wtpmdWt1aeGVSuW133leYwNoA01gr297BzVw + v/8CA0gBBaDYtzkw87ns6PhI+czM0JHjp/PFUjmZSmUM07RCKUPP6XVae/Vq + fbdys1ZbvOX5ja2+ULcP0Opbt18H/G8Ah+shDWQPzVQ/RSnLTGRsO5U0TMuM + VKjC0PUjLd1+fgPAOxTybl9YcvdC9VcBDobV3x0JINm3MfYbmdX/hu57FfZF + Dgot6Fe8eqfw3wLwzvVmX9jsvx8AHEAcnn91/BlySEFKTpuCtgAAABN0RVh0 + QXV0aG9yAHdhcnN6YXdpYW5rYQy+S5cAAABYdEVYdENvcHlyaWdodABDQzAg + UHVibGljIERvbWFpbiBEZWRpY2F0aW9uIGh0dHA6Ly9jcmVhdGl2ZWNvbW1v + bnMub3JnL3B1YmxpY2RvbWFpbi96ZXJvLzEuMC/G4735AAAAIXRFWHRDcmVh + dGlvbiBUaW1lADIwMTAtMDMtMjlUMDg6MDg6MzD47LxwAAAAJXRFWHRkYXRl + OmNyZWF0ZQAyMDIxLTA4LTE1VDIwOjU0OjM5LTA0OjAwNBT3DQAAACV0RVh0 + ZGF0ZTptb2RpZnkAMjAyMS0wOC0xNVQyMDo1NDoxMS0wNDowMDSDBqsAAADI + elRYdERlc2NyaXB0aW9uAAAY042OwQqCQBCGn6B3GOy+Cl0qTAjEc1HRJVhW + HXUrd2pmLXr7tDrVpcMP838w/F+wxxxyprsgB2ALclAxtRAbaBirRdB4f5mH + oTeuJlUxYoly8nRRxHW4HahO30SvmI5Y+CCBF4dPhzg0CYwOLs45GdKfG+sK + hBuy2H4xUlM1i76+BhcBwwirLj/bAlJqjXXzP9UyxmuHzp8feiknLPW6Q/H9 + moy3yK1oqvROUE2yH99suX45PwEyf2MTOoCNrQAAABl0RVh0U29mdHdhcmUA + d3d3Lmlua3NjYXBlLm9yZ5vuPBoAAABWdEVYdFNvdXJjZQBodHRwczovL29w + ZW5jbGlwYXJ0Lm9yZy9kZXRhaWwvMzUyMzMvdGFuZ28taW5ldHJuZXQtd2Vi + LWJyb3dzZXItYnktd2Fyc3phd2lhbmth5nAuRgAAACB0RVh0VGl0bGUAdGF + uZ28gaW5ldHJuZXQgd2ViIGJyb3dzZXLyr62TAAAAAElFTkSuQmCC +} + +set ::tk::icons::base_icon(.) icon + +pack [button $w.i -text "Set Window Icon to Globe" -image $::tk::icons::base_icon(.) \ + -compound top -command {wm iconphoto . $::tk::icons::base_icon(.) }] +pack [button $w.b -text "Set Badge to 3" -command {wm iconbadge . 3}] +pack [button $w.e -text "Set Badge to 11" -command {wm iconbadge . 11}] +pack [button $w.f -text "Reset Badge" -command {wm iconbadge . ""}] + +## See Code / Dismiss buttons +pack [addSeeDismiss $w.buttons $w] -side bottom -fill x Index: library/entry.tcl ================================================================== --- library/entry.tcl +++ library/entry.tcl @@ -207,13 +207,11 @@ bind Entry {# nothing} bind Entry {# nothing} bind Entry {# nothing} bind Entry {# nothing} bind Entry {# nothing} -if {[tk windowingsystem] eq "aqua"} { - bind Entry {# nothing} -} +bind Entry {# nothing} # Tk-on-Cocoa generates characters for these two keys. [Bug 2971663] bind Entry <> {# nothing} bind Entry <> {# nothing} # On Windows, paste is done using Shift-Insert. Shift-Insert already @@ -276,22 +274,35 @@ bind Entry <> { dict set ::tk::Priv(IMETextMark) "%W" [%W index insert] } bind Entry <> { - if {[catch {dict get $::tk::Priv(IMETextMark) "%W"} mark]} { - bell - } else { - %W selection range $mark insert - } + ::tk::EntryEndIMEMarkedText %W } bind Entry <> { %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert] } bind Entry <> { tk::EntryBackspace %W } + +# ::tk::EntryEndIMEMarkedText -- +# Handles input method text marking in an entry +# +# Arguments: +# w - The entry window. + +proc ::tk::EntryEndIMEMarkedText {w} { + variable Priv + if {[catch { + set mark [dict get $Priv(IMETextMark) $w] + }]} { + bell + return + } + $w selection range $mark insert +} # A few additional bindings of my own. bind Entry { if {!$tk_strictMotif} { Index: library/fontchooser.tcl ================================================================== --- library/fontchooser.tcl +++ library/fontchooser.tcl @@ -1,11 +1,11 @@ # fontchooser.tcl - # # A themeable Tk font selection dialog. See TIP #324. # -# Copyright (C) 2008 Keith Vetter -# Copyright (C) 2008 Pat Thoyts +# Copyright © 2008 Keith Vetter +# Copyright © 2008 Pat Thoyts # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. namespace eval ::tk::fontchooser { @@ -109,11 +109,11 @@ -command, -font, -parent, -title or -visible" } set cache [dict create -parent $S(-parent) -title $S(-title) \ -font $S(-font) -command $S(-command)] - set r [tclParseConfigSpec [namespace which -variable S] $specs "" $args] + set r [tclParseConfigSpec [namespace which -variable S] $specs DONTSETDEFAULTS $args] if {![winfo exists $S(-parent)]} { set code [list TK LOOKUP WINDOW $S(-parent)] set err "bad window path name \"$S(-parent)\"" array set S $cache return -code error -errorcode $code $err @@ -245,10 +245,11 @@ grid $S(W).font x $S(W).style x $S(W).size x -in $outer -sticky w grid $S(W).efont x $S(W).estyle x $S(W).esize x $bbox -in $outer -sticky ew grid $S(W).lfonts x $S(W).lstyles x $S(W).lsizes x ^ -in $outer -sticky news grid $WE x $WS - - x ^ -in $outer -sticky news -pady {15 30} grid configure $bbox -sticky n + grid rowconfigure $outer 2 -weight 1 grid columnconfigure $outer {1 3 5} -minsize $minsize(gap) grid columnconfigure $outer {0 2 4} -weight 1 grid columnconfigure $outer 0 -minsize $minsize(fonts) grid columnconfigure $outer 2 -minsize $minsize(styles) grid columnconfigure $outer 4 -minsize $minsize(sizes) ADDED library/iconbadges.tcl Index: library/iconbadges.tcl ================================================================== --- /dev/null +++ library/iconbadges.tcl @@ -0,0 +1,254 @@ +# iconbadges.tcl -- +# +# Notification badges for Tk applications. +# +# +# Copyright © 2021 Kevin Walzer/WordTech Communications LLC + +namespace eval ::tk::icons {} + +image create photo ::tk::icons::1-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + kFBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/HBz/V1f/Rkb/BQX/Dw//oKD/////y8v/Bgb/Pz//ra3/+/v/ + zMz/Li7/5ub/+vr/8fH/Ly//uLj/Zmb/n5//Bwf/Dg7/kpL/YWH/rq7/h4f/Cgr/ + AQH/AgLXmjE+AAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRBib + aYUeAAAAnElEQVQY022Q5w6DMBCD78hi03RQuvegg77/25ULCakq/MenT4piGwAQ + A8aFlIKzABGAiAojbRSFihhinOheSdwyVKn+UaoQsry7x5PpjDzPgBWGlPNqUdJR + MODky9V6U20N0hwE2W5/ODokQJKdzperQ7JDt7uuPRL299o/5P+IuxA9akO4qI/n + 622jukLNp3GFBmoPjOMnHNkJv3kDExXHctm+AAAAJXRFWHRkYXRlOmNyZWF0ZQAy + MDIxLTA4LTEwVDA4OjM1OjE0LTA0OjAw0aX6GwAAACV0RVh0ZGF0ZTptb2RpZnkA + MjAyMS0wOC0xMFQwODozNToxNC0wNDowMKD4QqcAAAAASUVORK5CYII= +} +image create photo ::tk::icons::2-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 21BMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/Cwv/ODj/UlL/UFD/MjL/CAj/ExP/oKD/8fH//v7//f3/7u7/ + kJD/DAz/ZWX/9fX/jIz/lpb/+vr/9/f/TEz/TU3/m5v/iYn/Ly//6+v/////YmL/ + nJz/5OT/MDD/KSn/srL/7Oz/ZGT/AQH/Nzf/zs7/zc3/SUn/AgL/ICD/ysr/7e3/ + gYH/VVX/WVn/Kir/fX3/eXn/AwP/dnb/rKz/qan/q6vjChO4AAAAEXRSTlMAAA5V + q9/4NK/0St3cDa7z4Pnet34AAAABYktHRCy63XGrAAAAwElEQVQY021Q1xLCMAxz + uktpS9hQoOwZ9t57/P8XUSesB/RinXz2SQIAQiRZUTVNVWSJEABUdMOkHKaho0ZI + yKIfWKFAI3qY/iCsE7AdZNFYPJFMIXNskN1gpjNZL5cv+AF1ZVBwVfRK5Uq1Vkeu + gIqj0Wz57Q7rIldBe/1N91h/gER7S8ORN55MhcQP6WzOFssVFYf8/XrDtrv94Sje + cxMnxnEWJtDq5Xq7B3gkhFUeaCUwFYH+xP5TzrfCyKvCJ3EzGUFH/1QDAAAAJXRF + WHRkYXRlOmNyZWF0ZQAyMDIxLTA4LTEwVDA4OjM1OjE0LTA0OjAw0aX6GwAAACV0 + RVh0ZGF0ZTptb2RpZnkAMjAyMS0wOC0xMFQwODozNToxNC0wNDowMKD4QqcAAAAA + SUVORK5CYII= +} +image create photo ::tk::icons::3-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + +VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/CQn/NTX/UlL/Tk7/Kir/BAT/ERH/mZn/8PD/+Pj/+vr/5ub/ + cHD/AgL/Vlb/9PT/5eX/X1//nZ3/////29v/HR3/Fhb/QED/RET/Cwv/f3//1dX/ + Ghr/Bwf/mpr/9vb/+fn/b2//lZX/2tr//Pz/wsL/Jyf/Dg7/Bgb/MzP/c3P/XV3/ + wMD/qqr/ExP/KSn/4+P/bm7/Q0P/6ur/vb3/x8f/19f/KCj/SEj/qan/zc3/y8v/ + oKD/ODj/BQX/DQ3/AwON+4wDAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34A + AAABYktHRCXDAckPAAAAx0lEQVQY021Q1RLCQBDbo4qW4l7ssOLu7g7//zH07oo8 + kJfNZGczyQIAQhaOF0RR4DkLQgBEkWSrSmGVJaIhZLOrH9hthoYkh/oDh4TA6SLM + 4/X5A0HCXE7gFGOGwpFoLJ7QDKpwwJNVMpXOZHEuTzgPAhmFYkkv40qVcAFEZlur + N5otysS3pLc73V6fSfRQ8wyGozges0NqP5nO5oslXjF7GmK96W53eH9gIWhU7Xg6 + X643M6pZ6D54PN+F/tT+85zvC93mC1+z9hl5VNGhJwAAACV0RVh0ZGF0ZTpjcmVh + dGUAMjAyMS0wOC0xMFQwODozNToxNC0wNDowMNGl+hsAAAAldEVYdGRhdGU6bW9k + aWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTQtMDQ6MDCg+EKnAAAAAElFTkSuQmCC +} +image create photo ::tk::icons::4-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 1VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/AgL/OTn/W1v/ODj/QED/4uL/////oaH/AQH/KSn/zs7/oqL/ + Fhb/tbX/9PT/1NT/Cgr/l5f//Pz/h4f/fHz/dXX/+/v/trb/HBz/fX3/qKj/DAz/ + EBD/ysr/4eH/zc3/5eX/8fH/lJT/BAT/Dw//uLj/5+f/5ub/8vL/+vr/paX/BQX/ + HR3/JCT/ISH/iYn/sLD/Ghr/Tk7/rq7/a2vT0ZXAAAAAEXRSTlMAAA5Vq9/4NK/0 + St3cDa7z4Pnet34AAAABYktHRBibaYUeAAAAvklEQVQY022QVRPCMBCEL1RSg5Ji + Ibi7W9Hi//8n0aRBHtiXvflm7mZvAQChmKJquq6pSgwhAE6wYRIh08CcIWTZ5CPb + ChnCDvmRgxHEE9HspdIZ7ok4KG6EsjmaZ6G7CqgRKRQpLXFEVNAEKVeqNYk00LnV + G81WWyJdINbp9voDOhxFiC+OJ3Q6m9PFciUW+fn1xt/6O7o/HMV5HsI7BcH5Qq83 + JkK8o5L74ymjfh5iHpMP/Xn7TznfCpOywhdM6Ra8aC+AYwAAACV0RVh0ZGF0ZTpj + cmVhdGUAMjAyMS0wOC0xMFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6 + bW9kaWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC +} +image create photo ::tk::icons::5-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 7VBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/ICD/MjL/Li7/CQn/Bgb/q6v/8/P/8vL/9PT/4uL/FRX/0tL/ + ////wsL/xcX/uLj/Jib/Kyv/6ur/8fH/aGj/XV3/SUn/Fhb/AQH/+Pj//Pz/7Oz/ + +fn/l5f/Dg7/ODj/qan/sLD/W1v/fn7/9/f/+vr/WVn/EBD/Ghr/2dn/gID/X1// + oKD/EhL/5OT/Y2P/S0v/7e3/vb3/ycn/yMj/HR3/AwP/Skr/zc3/LCz/BQX/DAz/ + AgKLBoLHAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRB5yCiAr + AAAAyUlEQVQY021Q1RLDMAxzVhp1XcbYMXXMzIz//zmLk9HD9GKdzvZJAgBCbJKs + qKoiSzZCAFDR7A7K4bBrqBHidNEPXE6mEc1Nf+DWCOgeZD4/QyDImEcHyWAzFI5E + I7F4gFFDAhmXEkkzmUpnsshlUHDk8oViqVyxkCug4ihXa/VGtNlCrgqp3en2+oPh + SEj80AqO6WRqzsQhfz/PLJa5lbkW77mJzba225uHozDBrZ7Oncu+eaXC6ivQrXV/ + vAP9if2nnG+F3leFT2jDGOnV8F/uAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDIxLTA4 + LTEwVDA4OjM1OjE1LTA0OjAwd9LxrwAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyMS0w + OC0xMFQwODozNToxNS0wNDowMAaPSRMAAAAASUVORK5CYII= +} +image create photo ::tk::icons::6-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 9lBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/AQH/ICD/S0v/UlL/NDT/CAj/WVn/2dn/+Pj/+fn/8PD/jY3/ + Cgr/LCz/4OD//f3/hob/cHD/5eX/1NT/NTX/bGz/////39//T0//Bwf/j4//5ub/ + wcH/7+//4uL/f3//CQn/lpb/+/v/n5//iIj/8vL/9/f/UVH/hYX/3t7/Hx//vb3/ + VVX/6Oj/MzP/ExP/x8f/e3v/EhL/t7f/0tL/wMD/MTH/IiL/xsb/zc3/qKj/QkL/ + AgL/Cwv/Dg7/BQWiS7IgAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAAB + YktHRCi9sLWyAAAAyklEQVQY021Q1RLCQBDbowalBYq7y+FWirs7/P/PwPawB/Ky + mezsThIAIMTC8YIoCjxnIQQAFclq00zYrBJqhMh27QO7/NSIpGg/UCQCqgOZ2+P1 + +QPIHCpwTlSCoXAkGos/qZMDHleJZCqdyebyyHkQcBRoMeEvecrIBRBxVGi1Vm80 + W8hFJrWp3jG6vT6TzMMBHY4CY2qwQ/P9RJ/O5gu6ZO9NE6s13Wz14o6ZYFb3scPx + dHYzq69Al+vt/g70J/afcr4Vul4VPgDLCRmO3FuJegAAACV0RVh0ZGF0ZTpjcmVh + dGUAMjAyMS0wOC0xMFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9k + aWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC +} +image create photo ::tk::icons::7-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + xlBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/Hh7/Njb/NTX/Ghr/i4v/9/f/8/P/8vL/8fH/9PT/eHj/fHz/ + 3Nz/2Nj/19f/6Oj/////+Pj/YGD/DQ3/Fxf/FRX/IiL/trb/j4//CQn/Zmb/+/v/ + xsb/GBj/HR3/0tL//f3/Xl7/ZGT/1dX/BAT/p6f/n5//AQH/Fhb/09P/c3P/GRn/ + mZn/qqr/PT3/AgKXVg1iAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAAB + YktHRCJdZVysAAAAu0lEQVQY022Q1xKCMBBFN5LQixFR7Bp77wU7//9TJgTFB+7L + njmTydxdAECooGCiqgQrBYQAhNF0gyYxdE04hEyL/mKZ3CHNpn+xNQSOy6Hkl3n8 + gKPrgOLxWamGYa3eaHL0FMDieavd6fZYfyAYAxFjOBpPpmw2F0xATf9dLFfrBNSv + 2mx3e5oqIuHAjoEkIr+npzO7RFJhWYJeb+wuDS+RVKWP5+stFa8qF4riOFsoZ+2c + 42QnLKYn/ADYChWCRPB9rQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0xMFQw + ODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgtMTBU + MDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC +} +image create photo ::tk::icons::8-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 6lBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/Bwf/MjL/UVH/TU3/Kir/BAT/DAz/j4//7e3/+Pj/5+f/eXn/ + BQX/Skr/9/f/7+//Z2f/fn7/+/v/6ur/MDD/UFD/4uL/Jib/QUH/9PT/NTX/EhL/ + srL/////09P/2tr/m5v/CAj/ycn//f3/y8v/1dX/s7P/GBj/hYX/HR3/Zmb/0dH/ + LCz/5eX/dHT/S0v/wsL/NDT/V1f/sLD/zc3/ysr/paX/RUX/AQH/Bgb/Dg7/DQ3m + iTf5AAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRC8j1CARAAAA + yklEQVQY021Q1RLCQBDbowZFSpEWh+J+xd3d/v936N5hD+QlmezsTrIAQIhLECVZ + lkTBRQgAOorbozN43Ap6hKhe/QOv6nhE8ek/8CkE/AFUoXAkapioAn4QNIdj8UQy + mUpnHKkJIOIom7PyhWKpjFoECalSrNbqDauJWgIZqdWmdod2e6hlbhn9wXBExxNu + scUptWfhFJ3zRXY+TheT5Yqu+XkWYmMNtkNa3fEQLGpmfziezpcrj/oqdLs/zHeh + P7X/POf7wuDrhU+46hlBGTVCQgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0x + MFQwODozNToxNS0wNDowMHfS8a8AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgt + MTBUMDg6MzU6MTUtMDQ6MDAGj0kTAAAAAElFTkSuQmCC +} +image create photo ::tk::icons::9-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + 8FBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/DAz/OTn/U1P/R0f/HBz/AQH/Fhb/oqL/8/P/+fn/+Pj/1NT/ + S0v/cXH/////29v/W1v/mJj/0ND/AgL/paX/np7/Ly//7e3//Pz/lZX/vr7/GBj/ + VVX/9fX/c3P/QED/5ub//f3/19f/4OD/+/v/eXn/Pz//mZn/oaH/dXX/6Oj/Z2f/ + Kir/cHD/enr/FRX/TU3/8PD/Ojr/Ozv/2tr/nJz/CAj/Tk7/sbH/z8//wcH/Bgb/ + Dw//CgoJOUsyAAAAEXRSTlMAAA5Vq9/4NK/0St3cDa7z4Pnet34AAAABYktHRCCz + az2AAAAAy0lEQVQY022Q1RLCQAxFs9QovlAozuLu7u72/39D0y3yQB6SO2cmmXsD + AITYBFGSZUkUbIQAIFHsKjVLtSvICHE46aecDoMRxUV/yqUQcHtQ+QNaMKSj8rhB + 8BozHInG4okkIq8AIs4US2eyLBdCLYJk9HyBFWmpXNEQSSDjqLJavdFkLdQyR+1O + t9cfsCFHuEj10XgynbE5XzTPL5ar9Sa+3fHzpon9rFI7sOOJmzCt5s+X6221tqxa + ge6Pp/4O9Cf2n+d8X+izXvgCm5cZM7QQ1AwAAAAldEVYdGRhdGU6Y3JlYXRlADIw + MjEtMDgtMTBUMDg6MzU6MTUtMDQ6MDB30vGvAAAAJXRFWHRkYXRlOm1vZGlmeQAy + MDIxLTA4LTEwVDA4OjM1OjE1LTA0OjAwBo9JEwAAAABJRU5ErkJggg== +} + +image create photo ::tk::icons::9plus-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAB + OFBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/ERH/AAD/NDT/AQH/AAD/AAD/Cgr/Nzf/U1P/SUn/Hx//AQH/mJj/8fH/+fn/ + 2dn/VFT/BAT/YmL//f3/4uL/YGD/j4//IyP/GBj/xsb/xcX/Fxf/lZX/////rKz/ + JSX/5eX/3t7/3Nz/AgL/hob/yMj/Hh7/Skr/fn7/MTH/srL/vr7/9fX/NDT/NTX/ + 39///v7/3d3/+vr/g4P/RET/9PT/+/v/8/P/R0f/OTn/lpb/pKT/c3P/4eH/dHT/ + Dw//Pz//VVX/5ub/ExP/JCT/bW3/fX3/Ghr/QUH/Rkb/Gxv/wsL/1dX/p6f/DAz/ + e3v/enr/Dg7/ra3/zs7/w8P/gYH/GRn/Bgb/CwuphzIHAAAAFHRSTlMAAA5Vq9/4 + NK/0St3cDa7z8/Ou4A5hHfoAAAABYktHRCy63XGrAAAA+ElEQVQY02NgYGBkZGJm + YWVjY2VhZmJkZGAAibBzcIqAAScHO0iMkZGLWwQOuLmAYozsPCJIgIedkYGXT1RM + XEJSCibGx8vAzC8tIysrJw/kKUhKKogIMDOwKCopq6gqyamJiKhraGqJiLAwsGrr + 6Erp6euoABUZGEoqGLEysBnrmJiayeiYW1haWVtbWdqwMbDZ2tnLOTjqODm7uNrb + u7q5szGwinh4enn76Pj6+QcE6gf4B7EysASHhIaFu1lHiIhEGhiGgYxnFvSxj4rW + iYkVEfGLi08AOYJXKCIxKTklFcmpQA+lJaRLIXsIi7exBA4iCIWhQQgAiNMk9J5+ + e/MAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjEtMDgtMTBUMDg6MzU6MTYtMDQ6MDBG + OusyAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDIxLTA4LTEwVDA4OjM1OjE2LTA0OjAw + N2dTjgAAAABJRU5ErkJggg== +} +image create photo ::tk::icons::!-badge -data { + iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAMAAABhEH5lAAAABGdBTUEAALGPC/xh + BQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAA + olBMVEUAAAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/AAD/ + AAD/AAD/AAD/AAD/Fhb/QED/Pj7/ExP/VVX/9PT/8PD/SUn/WFj//v7/+fn/S0v/ + SEj/PDz/MjL/6Oj/Jyf/ICD/4+P/2Nj/Fxf/Dw//qKj/nZ3/Cgr/IyP/hIT/gYH/ + Hh7/PT3/Ly//paX/oqL/KCj/AgL///8V6AjgAAAAEXRSTlMAAA5Vq9/4NK/0St3c + Da7z4Pnet34AAAABYktHRDXettlrAAAAoElEQVQY022QxxKCQBBEZ9hERkygophz + lv//NmF3Bz0wp1dd1V3dAwCIDuNCSsGZgwjQKMr1Un2eqxoN0Q/S9gK/1lCF6d+F + CiGKNfYHw5GGOAKWaBpn+URDwoAbw3RWzA1xEAYWRVYaEiANLPPV2pAkabPd7Umy + xsPxdCajjb9cb3eKtyXq+AeVsFWfr/eHqtKgqmoHdczueM7vhT37wi9PRRMHXNeq + aAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0wOC0xMFQwODozNToxNi0wNDowMEY6 + 6zIAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMDgtMTBUMDg6MzU6MTYtMDQ6MDA3 + Z1OOAAAAAElFTkSuQmCC +} + + +if {[tk windowingsystem] eq "x11"} { + + # ::tk::icons::IconBadge -- + # This procedure creates an icon with an overlay badge on systems that + # do not have a native icon/badge API. + # + # Arguments: + # win - window name + # badgenumber - badge number to draw over the window icon + + proc ::tk::icons::IconBadge {win badgenumber} { + + variable ::tk::icons::base_icon + + if {![info exists ::tk::icons::base_icon]} { + return -code error "::tk::icons::base_icon($win) must be set on X11" + } + + if {![info exists ::tk::icons::base_icon($win)]} { + return -code error "::tk::icons::base_icon($win) must be set on X11" + } + + if {[lsearch -exact [image names] $::tk::icons::base_icon($win)] <= 0} { + return -code error "can't use \"$::tk::icons::base_icon($win)\" as iconphoto: not a photo image" + } + + if {!([string is integer $badgenumber] && $badgenumber > 0) + && [string match $badgenumber "!"] == 0 + && $badgenumber ne ""} { + return -code error "can't use \"$badgenumber\" as icon badge" + } + + wm iconphoto $win $::tk::icons::base_icon($win) + + if {$badgenumber eq ""} { + return + } + + image create photo overlay + + switch -glob -- $badgenumber { + ! { + set badge ::tk::icons::!-badge + } + [1-9] { + set badge ::tk::icons::$badgenumber-badge + } + default { + set badge ::tk::icons::9plus-badge + } + + } + + overlay copy $::tk::icons::base_icon($win) + overlay copy $badge -from 0 0 18 18 -to 18 0 + wm iconphoto $win overlay + + } +} Index: library/iconlist.tcl ================================================================== --- library/iconlist.tcl +++ library/iconlist.tcl @@ -24,11 +24,11 @@ # selection clear ?? # selection get # selection includes # selection set ?? -package require Tk +package require tk ::tk::Megawidget create ::tk::IconList ::tk::FocusableWidget { variable w canvas sbar accel accelCB fill font index \ itemList itemsPerColumn list maxIH maxIW maxTH maxTW noScroll \ numItems oldX oldY options rect selected selection textList Index: library/icons.tcl ================================================================== --- library/icons.tcl +++ library/icons.tcl @@ -2,11 +2,11 @@ # # A set of stock icons for use in Tk dialogs. The icons used here # were provided by the Tango Desktop project which provides a # unified set of high quality icons licensed under the # Creative Commons Attribution Share-Alike license -# (http://creativecommons.org/licenses/by-sa/3.0/) +# (https://creativecommons.org/licenses/by-sa/3.0/) # # See http://tango.freedesktop.org/Tango_Desktop_Project # # Copyright © 2009 Pat Thoyts Index: library/listbox.tcl ================================================================== --- library/listbox.tcl +++ library/listbox.tcl @@ -3,11 +3,11 @@ # This file defines the default bindings for Tk listbox widgets # and provides procedures that help in implementing those bindings. # # Copyright © 1994 The Regents of the University of California. # Copyright © 1994-1995 Sun Microsystems, Inc. -# Copyright © 1998 by Scriptics Corporation. +# Copyright © 1998 Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. #-------------------------------------------------------------------------- @@ -175,20 +175,20 @@ bind Listbox { %W scan dragto %x %y } bind Listbox { - tk::MouseWheel %W y %D -30.0 + tk::MouseWheel %W y %D -40.0 } bind Listbox { - tk::MouseWheel %W y %D -3.0 + tk::MouseWheel %W y %D -12.0 } bind Listbox { - tk::MouseWheel %W x %D -30.0 + tk::MouseWheel %W x %D -40.0 } bind Listbox { - tk::MouseWheel %W x %D -3.0 + tk::MouseWheel %W x %D -12.0 } # ::tk::ListboxBeginSelect -- # # This procedure is typically invoked on button-1 presses. It begins @@ -246,11 +246,11 @@ set Priv(listboxPrev) $el tk::FireListboxSelectEvent $w } extended { set i $Priv(listboxPrev) - if {$i eq ""} { + if {$i < 0} { set i $el $w selection set $el } if {[$w selection includes anchor]} { $w selection clear $i $el @@ -456,11 +456,11 @@ if {[$w cget -selectmode] ne "extended"} { return } set first [$w index anchor] set last $Priv(listboxPrev) - if {$last eq ""} { + if {$last < 0} { # Not actually doing any selection right now return } if {$first > $last} { set tmp $first Index: library/megawidget.tcl ================================================================== --- library/megawidget.tcl +++ library/megawidget.tcl @@ -8,11 +8,11 @@ # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # -package require Tk +package require tk ::oo::class create ::tk::Megawidget { superclass ::oo::class method unknown {w args} { if {[string match .* $w]} { Index: library/menu.tcl ================================================================== --- library/menu.tcl +++ library/menu.tcl @@ -4,11 +4,11 @@ # It also implements keyboard traversal of menus and implements a few # other utility procedures related to menus. # # Copyright © 1992-1994 The Regents of the University of California. # Copyright © 1994-1997 Sun Microsystems, Inc. -# Copyright © 1998-1999 by Scriptics Corporation. +# Copyright © 1998-1999 Scriptics Corporation. # Copyright © 2007 Daniel A. Steffen # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # @@ -267,12 +267,12 @@ set cur $Priv(postedMb) if {$cur ne ""} { MenuUnpost {} } if {$::tk_strictMotif} { - set Priv(cursor) [$w cget -cursor] - $w configure -cursor arrow + set Priv(cursor) [$w cget -cursor] + $w configure -cursor arrow } if {[tk windowingsystem] ne "aqua"} { set Priv(relief) [$w cget -relief] $w configure -relief raised } else { @@ -279,11 +279,11 @@ $w configure -state active } set Priv(postedMb) $w set Priv(focus) [focus] - $menu activate none + $menu activate {} GenerateMenuSelect $menu update idletasks if {[catch {PostMenubuttonMenu $w $menu} msg opt]} { # Error posting menu (e.g. bogus -postcommand). Unpost it and @@ -341,11 +341,11 @@ if {$mb ne ""} { set menu [$mb cget -menu] $menu unpost set Priv(postedMb) {} if {$::tk_strictMotif} { - $mb configure -cursor $Priv(cursor) + $mb configure -cursor $Priv(cursor) } if {[tk windowingsystem] ne "aqua"} { $mb configure -relief $Priv(relief) } else { $mb configure -state normal @@ -362,12 +362,12 @@ while {1} { set parent [winfo parent $menu] if {[winfo class $parent] ne "Menu" || ![winfo ismapped $parent]} { break } - $parent activate none - $parent postcascade none + $parent activate {} + $parent postcascade {} GenerateMenuSelect $parent set type [$parent cget -type] if {$type eq "menubar" || $type eq "tearoff"} { break } @@ -473,38 +473,40 @@ # state - Modifier state (tells whether buttons are down). proc ::tk::MenuMotion {menu x y state} { variable ::tk::Priv if {$menu eq $Priv(window)} { - set activeindex [$menu index active] + set activeindex [$menu index active] if {[$menu cget -type] eq "menubar"} { if {[info exists Priv(focus)] && $menu ne $Priv(focus)} { $menu activate @$x,$y GenerateMenuSelect $menu } } else { $menu activate @$x,$y GenerateMenuSelect $menu } - set index [$menu index @$x,$y] - if {[info exists Priv(menuActivated)] \ - && $index ne "none" \ - && $index ne $activeindex} { - set mode [option get $menu clickToFocus ClickToFocus] - if {[string is false $mode]} { - set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}] - if {[$menu type $index] eq "cascade"} { - # Catch these postcascade commands since the menu could be - # destroyed before they run. - set Priv(menuActivatedTimer) \ - [after $delay "catch {$menu postcascade active}"] - } else { - set Priv(menuDeactivatedTimer) \ - [after $delay "catch {$menu postcascade none}"] - } - } - } + set index [$menu index @$x,$y] + if {[info exists Priv(menuActivated)] \ + && $index >= 0 \ + && $index ne $activeindex} { + set mode [option get $menu clickToFocus ClickToFocus] + if {[string is false $mode]} { + set delay [expr {[$menu cget -type] eq "menubar" ? 0 : 50}] + if {[$menu type $index] eq "cascade"} { + # Catch these postcascade commands since the menu could be + # destroyed before they run. + set Priv(menuActivatedTimer) \ + [after $delay [list catch [list \ + $menu postcascade active]]] + } else { + set Priv(menuDeactivatedTimer) \ + [after $delay [list catch [list + $menu postcascade {}]]] + } + } + } } } # ::tk::MenuButtonDown -- # Handles button presses in menus. There are a couple of tricky things @@ -523,17 +525,17 @@ proc ::tk::MenuButtonDown menu { variable ::tk::Priv if {![winfo viewable $menu]} { - return + return } - if {[$menu index active] eq "none"} { - if {[$menu cget -type] ne "menubar" } { - set Priv(window) {} - } - return + if {[$menu index active] < 0} { + if {[$menu cget -type] ne "menubar" } { + set Priv(window) {} + } + return } $menu postcascade active if {$Priv(postedMb) ne "" && [winfo viewable $Priv(postedMb)]} { grab -global $Priv(postedMb) } else { @@ -550,11 +552,11 @@ $menu configure -cursor arrow } if {[$menu type active] eq "cascade"} { set Priv(menuActivated) 1 } - } + } # Don't update grab information if the grab window isn't changing. # Otherwise, we'll get an error when we unpost the menus and # restore the grab, since the old grab window will not be viewable # anymore. @@ -583,19 +585,19 @@ # state - Modifier state. proc ::tk::MenuLeave {menu rootx rooty state} { variable ::tk::Priv set Priv(window) {} - if {[$menu index active] eq "none"} { + if {[$menu index active] < 0} { return } if {[$menu type active] eq "cascade" \ && [winfo containing $rootx $rooty] eq \ [$menu entrycget active -menu]} { return } - $menu activate none + $menu activate {} GenerateMenuSelect $menu } # ::tk::MenuInvoke -- # This procedure is invoked when button 1 is released over a menu. @@ -613,12 +615,12 @@ if {$buttonRelease && $Priv(window) eq ""} { # Mouse was pressed over a menu without a menu button, then # dragged off the menu (possibly with a cascade posted) and # released. Unpost everything and quit. - $w postcascade none - $w activate none + $w postcascade {} + $w activate {} event generate $w <> MenuUnpost $w return } if {[$w type active] eq "cascade"} { @@ -627,20 +629,20 @@ MenuFirstEntry $menu } elseif {[$w type active] eq "tearoff"} { ::tk::TearOffMenu $w MenuUnpost $w } elseif {[$w cget -type] eq "menubar"} { - $w postcascade none + $w postcascade {} set active [$w index active] set isCascade [string equal [$w type $active] "cascade"] # Only de-activate the active item if it's a cascade; this prevents # the annoying "activation flicker" you otherwise get with # checkbuttons/commands/etc. on menubars if { $isCascade } { - $w activate none + $w activate {} event generate $w <> } MenuUnpost $w @@ -651,11 +653,11 @@ if { !$isCascade } { uplevel #0 [list $w invoke $active] } } else { set active [$w index active] - if {$Priv(popup) eq "" || $active ne "none"} { + if {$Priv(popup) eq "" || $active >= 0} { MenuUnpost $w } uplevel #0 [list $w invoke active] } } @@ -755,15 +757,15 @@ } } else { set count -1 set m2 [winfo parent $menu] if {[winfo class $m2] eq "Menu"} { - $menu activate none + $menu activate {} GenerateMenuSelect $menu tk_menuSetFocus $m2 - $m2 postcascade none + $m2 postcascade {} if {[$m2 cget -type] ne "menubar"} { return } } @@ -795,11 +797,11 @@ } set mb [lindex $buttons $i] if {[winfo class $mb] eq "Menubutton" \ && [$mb cget -state] ne "disabled" \ && [$mb cget -menu] ne "" \ - && [[$mb cget -menu] index last] ne "none"} { + && [[$mb cget -menu] index last] >= 0} { break } if {$mb eq $w} { return } @@ -817,17 +819,18 @@ # menu - Menu window that received the keystroke. # count - 1 means go to the next lower entry, # -1 means go to the next higher entry. proc ::tk::MenuNextEntry {menu count} { - if {[$menu index last] eq "none"} { + set last [$menu index last] + if {$last < 0} { return } set length [expr {[$menu index last]+1}] set quitAfter $length set active [$menu index active] - if {$active eq "none"} { + if {$active < 0} { set i 0 } else { set i [expr {$active + $count}] } while {1} { @@ -891,11 +894,11 @@ set char [string tolower $char] set windowlist [winfo child $w] foreach child $windowlist { # Don't descend into other toplevels. - if {[winfo toplevel $w] ne [winfo toplevel $child]} { + if {[winfo toplevel $w] ne [winfo toplevel $child]} { continue } if {[winfo class $child] eq "Menu" && \ [$child cget -type] eq "menubar"} { if {$char eq ""} { @@ -917,11 +920,11 @@ } } foreach child $windowlist { # Don't descend into other toplevels. - if {[winfo toplevel $w] ne [winfo toplevel $child]} { + if {[winfo toplevel $w] ne [winfo toplevel $child]} { continue } switch -- [winfo class $child] { Menubutton { set char2 [string index [$child cget -text] \ @@ -1024,13 +1027,10 @@ if {$char eq ""} { return } set char [string tolower $char] set last [$w index last] - if {$last eq "none"} { - return - } for {set i 0} {$i <= $last} {incr i} { if {[catch {set char2 [string index \ [$w entrycget $i -label] [$w entrycget $i -underline]]}]} { continue } @@ -1066,17 +1066,14 @@ proc ::tk::MenuFirstEntry menu { if {$menu eq ""} { return } tk_menuSetFocus $menu - if {[$menu index active] ne "none"} { + if {[$menu index active] >= 0} { return } set last [$menu index last] - if {$last eq "none"} { - return - } for {set i 0} {$i <= $last} {incr i} { if {([catch {set state [$menu entrycget $i -state]}] == 0) \ && $state ne "disabled" && [$menu type $i] ne "tearoff"} { $menu activate $i GenerateMenuSelect $menu @@ -1112,13 +1109,10 @@ if {![regexp {^active$|^last$|^none$|^[0-9]|^@} $s]} { catch {set i [$menu index $s]} return $i } set last [$menu index last] - if {$last eq "none"} { - return - } for {set i 0} {$i <= $last} {incr i} { if {![catch {$menu entrycget $i -label} label]} { if {$label eq $s} { return $i } @@ -1184,11 +1178,11 @@ above { incr y [expr {-[winfo reqheight $menu]}] # if we go offscreen to the top, show as 'below' if {$y < [winfo vrooty $button]} { set y [expr {[winfo vrooty $button] + [winfo rooty $button]\ - + [winfo reqheight $button]}] + + [winfo reqheight $button]}] } set entry {} } below { incr y [winfo height $button] @@ -1367,13 +1361,13 @@ if {$Priv(popup) ne "" || $Priv(postedMb) ne ""} { tk::MenuUnpost {} } tk::PostOverPoint $menu $x $y $entry if {[tk windowingsystem] eq "x11" && [winfo viewable $menu]} { - tk::SaveGrabInfo $menu + tk::SaveGrabInfo $menu grab -global $menu set Priv(popup) $menu set Priv(window) $menu set Priv(menuActivated) 1 tk_menuSetFocus $menu } } Index: library/msgs/cs.msg ================================================================== --- library/msgs/cs.msg +++ library/msgs/cs.msg @@ -72,6 +72,24 @@ ::msgcat::mcset cs "ignore" "ignorovat" ::msgcat::mcset cs "ok" ::msgcat::mcset cs "red" "červeá" ::msgcat::mcset cs "retry" "znovu" ::msgcat::mcset cs "yes" "ano" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset cs "Print" "Tisknout" + ::msgcat::mcset cs "Printer" "Tiskárna" + ::msgcat::mcset cs "Letter " "Dopis " + ::msgcat::mcset cs "Legal " "Legální " + ::msgcat::mcset cs "A4" "A4" + ::msgcat::mcset cs "Grayscale" "Stupně Šedi" + ::msgcat::mcset cs "RGB" "RGB" + ::msgcat::mcset cs "Options" "Možnosti" + ::msgcat::mcset cs "Copies" "Kopie" + ::msgcat::mcset cs "Paper" "Papír" + ::msgcat::mcset cs "Scale" "Škála" + ::msgcat::mcset cs "Orientation" "Orientace" + ::msgcat::mcset cs "Portrait" "Portrét" + ::msgcat::mcset cs "Landscape" "Krajina" + ::msgcat::mcset cs "Output" "Výstup" } Index: library/msgs/da.msg ================================================================== --- library/msgs/da.msg +++ library/msgs/da.msg @@ -73,6 +73,24 @@ ::msgcat::mcset da "ignore" "ignorer" ::msgcat::mcset da "ok" ::msgcat::mcset da "red" "rød" ::msgcat::mcset da "retry" "gentag" ::msgcat::mcset da "yes" "ja" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset da "Print" "Trykke" + ::msgcat::mcset da "Printer" "Printer" + ::msgcat::mcset da "Letter " "Brev" + ::msgcat::mcset da "Legal " "Juridisk" + ::msgcat::mcset da "A4" "A4" + ::msgcat::mcset da "Grayscale" "Gråtoneskala" + ::msgcat::mcset da "RGB" "Rgb" + ::msgcat::mcset da "Options" "Indstillinger" + ::msgcat::mcset da "Copies" "Kopier" + ::msgcat::mcset da "Paper" "Papir" + ::msgcat::mcset da "Scale" "Skalere" + ::msgcat::mcset da "Orientation" "Orientering" + ::msgcat::mcset da "Portrait" "Portræt" + ::msgcat::mcset da "Landscape" "Landskab" + ::msgcat::mcset da "Output" "Udskriv Publikation" } Index: library/msgs/de.msg ================================================================== --- library/msgs/de.msg +++ library/msgs/de.msg @@ -86,6 +86,24 @@ ::msgcat::mcset de "ignore" "ignorieren" ::msgcat::mcset de "ok" ::msgcat::mcset de "red" "rot" ::msgcat::mcset de "retry" "wiederholen" ::msgcat::mcset de "yes" "ja" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset de "Print" "Drucken" + ::msgcat::mcset de "Printer" "Drucker" + ::msgcat::mcset de "Letter " "Brief" + ::msgcat::mcset de "Legal " "Rechtlich" + ::msgcat::mcset de "A4" "A4" + ::msgcat::mcset de "Grayscale" "Graustufen" + ::msgcat::mcset de "RGB" "Rgb" + ::msgcat::mcset de "Options" "Optionen" + ::msgcat::mcset de "Copies" "Kopien" + ::msgcat::mcset de "Paper" "Papier" + ::msgcat::mcset de "Scale" "Skala" + ::msgcat::mcset de "Orientation" "Ausrichtung" + ::msgcat::mcset de "Portrait" "Porträt" + ::msgcat::mcset de "Landscape" "Landschaft" + ::msgcat::mcset de "Output" "Ausgabe" } Index: library/msgs/el.msg ================================================================== --- library/msgs/el.msg +++ library/msgs/el.msg @@ -81,6 +81,24 @@ ::msgcat::mcset el "ignore" "αγνόηση" ::msgcat::mcset el "ok" "εντάξει" ::msgcat::mcset el "red" "κόκκινο" ::msgcat::mcset el "retry" "προσπάθησε ξανά" ::msgcat::mcset el "yes" "ναι" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset el "Print" "Τυπώνω" + ::msgcat::mcset el "Printer" "Εκτυπωτής" + ::msgcat::mcset el "Letter " "Γράμμα" + ::msgcat::mcset el "Legal " "Νομικός" + ::msgcat::mcset el "A4" "Α4" + ::msgcat::mcset el "Grayscale" "Κλίμακα Του Γκρι" + ::msgcat::mcset el "RGB" "Rgb" + ::msgcat::mcset el "Options" "Επιλογές" + ::msgcat::mcset el "Copies" "Αντίγραφα" + ::msgcat::mcset el "Paper" "Χαρτί" + ::msgcat::mcset el "Scale" "Κλίμακα" + ::msgcat::mcset el "Orientation" "Προσανατολισμός" + ::msgcat::mcset el "Portrait" "Προσωπογραφία" + ::msgcat::mcset el "Landscape" "Τοπίο" + ::msgcat::mcset el "Output" "Έξοδος" } Index: library/msgs/en.msg ================================================================== --- library/msgs/en.msg +++ library/msgs/en.msg @@ -87,5 +87,24 @@ ::msgcat::mcset en "ok" ::msgcat::mcset en "red" ::msgcat::mcset en "retry" ::msgcat::mcset en "yes" } + +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset en "Print" + ::msgcat::mcset en "Printer" + ::msgcat::mcset en "Letter " + ::msgcat::mcset en "Legal " + ::msgcat::mcset en "A4" + ::msgcat::mcset en "Grayscale" + ::msgcat::mcset en "RGB" + ::msgcat::mcset en "Options" + ::msgcat::mcset en "Copies" + ::msgcat::mcset en "Paper" + ::msgcat::mcset en "Scale" + ::msgcat::mcset en "Orientation" + ::msgcat::mcset en "Portrait" + ::msgcat::mcset en "Landscape" + ::msgcat::mcset en "Output" +} Index: library/msgs/eo.msg ================================================================== --- library/msgs/eo.msg +++ library/msgs/eo.msg @@ -70,6 +70,24 @@ ::msgcat::mcset eo "green" "verda" ::msgcat::mcset eo "ignore" "ignorieren" ::msgcat::mcset eo "red" "ruĝa" ::msgcat::mcset eo "retry" "ripetu" ::msgcat::mcset eo "yes" "jes" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset eo "Print" "Presi" + ::msgcat::mcset eo "Printer" "Presilo" + ::msgcat::mcset eo "Letter " "Letero" + ::msgcat::mcset eo "Legal " "Laŭleĝa" + ::msgcat::mcset eo "A4" "A4" + ::msgcat::mcset eo "Grayscale" "Grizskalo" + ::msgcat::mcset eo "RGB" "RGB" + ::msgcat::mcset eo "Options" "Opcioj" + ::msgcat::mcset eo "Copies" "Kopioj" + ::msgcat::mcset eo "Paper" "Papero" + ::msgcat::mcset eo "Scale" "Skalo" + ::msgcat::mcset eo "Orientation" "Orientiĝo" + ::msgcat::mcset eo "Portrait" "Portreto" + ::msgcat::mcset eo "Landscape" "Pejzaĝo" + ::msgcat::mcset eo "Output" "Eligo" } Index: library/msgs/es.msg ================================================================== --- library/msgs/es.msg +++ library/msgs/es.msg @@ -71,6 +71,24 @@ ::msgcat::mcset es "ignore" "ignorar" ::msgcat::mcset es "ok" ::msgcat::mcset es "red" "rojo" ::msgcat::mcset es "retry" "reintentar" ::msgcat::mcset es "yes" "sí" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset es "Print" "Imprimir" + ::msgcat::mcset es "Printer" "Impresora" + ::msgcat::mcset es "Letter " "Carta" + ::msgcat::mcset es "Legal " "Legal" + ::msgcat::mcset es "A4" "A4" + ::msgcat::mcset es "Grayscale" "Escala De Grises" + ::msgcat::mcset es "RGB" "Rgb" + ::msgcat::mcset es "Options" "Opciones" + ::msgcat::mcset es "Copies" "Copias" + ::msgcat::mcset es "Paper" "Papel" + ::msgcat::mcset es "Scale" "Escama" + ::msgcat::mcset es "Orientation" "Orientación" + ::msgcat::mcset es "Portrait" "Retrato" + ::msgcat::mcset es "Landscape" "Paisaje" + ::msgcat::mcset es "Output" "Salida" } Index: library/msgs/fr.msg ================================================================== --- library/msgs/fr.msg +++ library/msgs/fr.msg @@ -67,6 +67,24 @@ ::msgcat::mcset fr "ignore" "ignorer" ::msgcat::mcset fr "ok" ::msgcat::mcset fr "red" "rouge" ::msgcat::mcset fr "retry" "réessayer" ::msgcat::mcset fr "yes" "oui" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset fr "Print" "Imprimer" + ::msgcat::mcset fr "Printer" "Imprimante" + ::msgcat::mcset fr "Letter " "Lettre" + ::msgcat::mcset fr "Legal " "Légal" + ::msgcat::mcset fr "A4" "A4" + ::msgcat::mcset fr "Grayscale" "Niveaux de Gris" + ::msgcat::mcset fr "RGB" "RVB" + ::msgcat::mcset fr "Options" "Options" + ::msgcat::mcset fr "Copies" "Nombre d'exemplaires" + ::msgcat::mcset fr "Paper" "Papier" + ::msgcat::mcset fr "Scale" "Échelle" + ::msgcat::mcset fr "Orientation" "Orientation" + ::msgcat::mcset fr "Portrait" "Portrait" + ::msgcat::mcset fr "Landscape" "Paysage" + ::msgcat::mcset fr "Output" "Sortie" } Index: library/msgs/hu.msg ================================================================== --- library/msgs/hu.msg +++ library/msgs/hu.msg @@ -73,6 +73,24 @@ ::msgcat::mcset hu "ignore" "ignorer" ::msgcat::mcset hu "ok" ::msgcat::mcset hu "red" "vörös" ::msgcat::mcset hu "retry" "újra" ::msgcat::mcset hu "yes" "igen" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset hu "Print" "Nyomtat" + ::msgcat::mcset hu "Printer" "Nyomtató" + ::msgcat::mcset hu "Letter " "Levél" + ::msgcat::mcset hu "Legal " "Törvényes" + ::msgcat::mcset hu "A4" "A4" + ::msgcat::mcset hu "Grayscale" "Szürkeárnyalatos" + ::msgcat::mcset hu "RGB" "Rgb" + ::msgcat::mcset hu "Options" "Beállítások" + ::msgcat::mcset hu "Copies" "Másolatok" + ::msgcat::mcset hu "Paper" "Papír" + ::msgcat::mcset hu "Scale" "Hangsor" + ::msgcat::mcset hu "Orientation" "Tájékozódás" + ::msgcat::mcset hu "Portrait" "Portré" + ::msgcat::mcset hu "Landscape" "Táj" + ::msgcat::mcset hu "Output" "Hozam" } Index: library/msgs/it.msg ================================================================== --- library/msgs/it.msg +++ library/msgs/it.msg @@ -68,6 +68,24 @@ ::msgcat::mcset it "ignore" "ignora" ::msgcat::mcset it "ok" ::msgcat::mcset it "red" "rosso" ::msgcat::mcset it "retry" "riprova" ::msgcat::mcset it "yes" "sì" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset it "Print" "Stampare" + ::msgcat::mcset it "Printer" "Stampante" + ::msgcat::mcset it "Letter " "Lettera" + ::msgcat::mcset it "Legal " "Legale" + ::msgcat::mcset it "A4" "A4" + ::msgcat::mcset it "Grayscale" "Scala Di Grigi" + ::msgcat::mcset it "RGB" "Rgb" + ::msgcat::mcset it "Options" "Opzioni" + ::msgcat::mcset it "Copies" "Copie" + ::msgcat::mcset it "Paper" "Carta" + ::msgcat::mcset it "Scale" "Scala" + ::msgcat::mcset it "Orientation" "Orientamento" + ::msgcat::mcset it "Portrait" "Ritratto" + ::msgcat::mcset it "Landscape" "Paesaggio" + ::msgcat::mcset it "Output" "Prodotto" } Index: library/msgs/nl.msg ================================================================== --- library/msgs/nl.msg +++ library/msgs/nl.msg @@ -86,6 +86,24 @@ ::msgcat::mcset nl "ignore" "negeren" ::msgcat::mcset nl "ok" ::msgcat::mcset nl "red" "rood" ::msgcat::mcset nl "retry" "opnieuw" ::msgcat::mcset nl "yes" "ja" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset nl "Print" "Afdrukken" + ::msgcat::mcset nl "Printer" "Printer" + ::msgcat::mcset nl "Letter " "Brief" + ::msgcat::mcset nl "Legal " "Legaal" + ::msgcat::mcset nl "A4" "A4" + ::msgcat::mcset nl "Grayscale" "Grijswaarden" + ::msgcat::mcset nl "RGB" "Rgb" + ::msgcat::mcset nl "Options" "Opties" + ::msgcat::mcset nl "Copies" "Kopieën" + ::msgcat::mcset nl "Paper" "Papier" + ::msgcat::mcset nl "Scale" "Schub" + ::msgcat::mcset nl "Orientation" "Oriëntatie" + ::msgcat::mcset nl "Portrait" "Portret" + ::msgcat::mcset nl "Landscape" "Landschap" + ::msgcat::mcset nl "Output" "Uitvoer" } Index: library/msgs/pl.msg ================================================================== --- library/msgs/pl.msg +++ library/msgs/pl.msg @@ -86,6 +86,24 @@ ::msgcat::mcset pl "ignore" "ignoruj" ::msgcat::mcset pl "ok" ::msgcat::mcset pl "red" "czerwony" ::msgcat::mcset pl "retry" "ponów" ::msgcat::mcset pl "yes" "tak" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset pl "Print" "Drukować" + ::msgcat::mcset pl "Printer" "Drukarka" + ::msgcat::mcset pl "Letter " "Litera" + ::msgcat::mcset pl "Legal " "Legalny" + ::msgcat::mcset pl "A4" "A4" + ::msgcat::mcset pl "Grayscale" "Skala Szarości" + ::msgcat::mcset pl "RGB" "Rgb" + ::msgcat::mcset pl "Options" "Opcje" + ::msgcat::mcset pl "Copies" "Kopie" + ::msgcat::mcset pl "Paper" "Papier" + ::msgcat::mcset pl "Scale" "Skala" + ::msgcat::mcset pl "Orientation" "Orientacja" + ::msgcat::mcset pl "Portrait" "Portret" + ::msgcat::mcset pl "Landscape" "Krajobraz" + ::msgcat::mcset pl "Output" "Produkt Wyjściowy" } Index: library/msgs/pt.msg ================================================================== --- library/msgs/pt.msg +++ library/msgs/pt.msg @@ -69,6 +69,24 @@ ::msgcat::mcset pt "ignore" "ignorar" ::msgcat::mcset pt "ok" ::msgcat::mcset pt "red" "vermelho" ::msgcat::mcset pt "retry" "tentar novamente" ::msgcat::mcset pt "yes" "sim" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset pt "Print" "Imprimir" + ::msgcat::mcset pt "Printer" "Impressora" + ::msgcat::mcset pt "Letter " "Letra" + ::msgcat::mcset pt "Legal " "Legal" + ::msgcat::mcset pt "A4" "A4" + ::msgcat::mcset pt "Grayscale" "Escala De Cinza" + ::msgcat::mcset pt "RGB" "Rgb" + ::msgcat::mcset pt "Options" "Opções" + ::msgcat::mcset pt "Copies" "Exemplares" + ::msgcat::mcset pt "Paper" "Papel" + ::msgcat::mcset pt "Scale" "Escala" + ::msgcat::mcset pt "Orientation" "Orientação" + ::msgcat::mcset pt "Portrait" "Retrato" + ::msgcat::mcset pt "Landscape" "Paisagem" + ::msgcat::mcset pt "Output" "Saída" } Index: library/msgs/ru.msg ================================================================== --- library/msgs/ru.msg +++ library/msgs/ru.msg @@ -71,5 +71,23 @@ ::msgcat::mcset ru "red" " красный" ::msgcat::mcset ru "retry" "повторить" ::msgcat::mcset ru "yes" "да" } +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset ru "Print" "Печатать" + ::msgcat::mcset ru "Printer" "Принтер" + ::msgcat::mcset ru "Letter " "Письмо" + ::msgcat::mcset ru "Legal " "Законный" + ::msgcat::mcset ru "A4" "A4" + ::msgcat::mcset ru "Grayscale" "Серый Масштаб" + ::msgcat::mcset ru "RGB" "Ргб" + ::msgcat::mcset ru "Options" "Параметры" + ::msgcat::mcset ru "Copies" "Копии" + ::msgcat::mcset ru "Paper" "Бумага" + ::msgcat::mcset ru "Scale" "Шкала" + ::msgcat::mcset ru "Orientation" "Ориентация" + ::msgcat::mcset ru "Portrait" "Портрет" + ::msgcat::mcset ru "Landscape" "Ландшафт" + ::msgcat::mcset ru "Output" "Выпуск" +} Index: library/msgs/sv.msg ================================================================== --- library/msgs/sv.msg +++ library/msgs/sv.msg @@ -71,6 +71,24 @@ ::msgcat::mcset sv "ignore" "ignorera" ::msgcat::mcset sv "ok" ::msgcat::mcset sv "red" "röd" ::msgcat::mcset sv "retry" "försök igen" ::msgcat::mcset sv "yes" "ja" +} +#localization of print terms by Kevin Walzer via Microsoft Translator +namespace eval ::tk { + ::msgcat::mcset sv "Print" "Trycka" + ::msgcat::mcset sv "Printer" "Skrivare" + ::msgcat::mcset sv "Letter " "Brev" + ::msgcat::mcset sv "Legal " "Laglig" + ::msgcat::mcset sv "A4" "A4 (På 199" + ::msgcat::mcset sv "Grayscale" "Gråskala" + ::msgcat::mcset sv "RGB" "Rgb" + ::msgcat::mcset sv "Options" "Alternativ" + ::msgcat::mcset sv "Copies" "Kopior" + ::msgcat::mcset sv "Paper" "Papper" + ::msgcat::mcset sv "Scale" "Skala" + ::msgcat::mcset sv "Orientation" "Orientering" + ::msgcat::mcset sv "Portrait" "Porträtt" + ::msgcat::mcset sv "Landscape" "Landskap" + ::msgcat::mcset sv "Output" "Utdata" } ADDED library/print.tcl Index: library/print.tcl ================================================================== --- /dev/null +++ library/print.tcl @@ -0,0 +1,995 @@ +# print.tcl -- + +# This file defines the 'tk print' command for printing of the canvas +# widget and text on X11, Windows, and macOS. It implements an abstraction +# layer that presents a consistent API across the three platforms. + +# Copyright © 2009 Michael I. Schwartz. +# Copyright © 2021 Kevin Walzer/WordTech Communications LLC. +# Copyright © 2021 Harald Oehlmann, Elmicron GmbH +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +namespace eval ::tk::print { + namespace import -force ::tk::msgcat::* + + # makeTempFile: + # Create a temporary file and populate its contents + # Arguments: + # filename - base of the name of the file to create + # contents - what to put in the file; defaults to empty + # Returns: + # Full filename for created file + # + proc makeTempFile {filename {contents ""}} { + set f [file tempfile filename $filename] + try { + puts -nonewline $f $contents + return $filename + } finally { + close $f + } + } + + if {[tk windowingsystem] eq "win32"} { + variable printer_name + variable copies + variable dpi_x + variable dpi_y + variable paper_width + variable paper_height + variable margin_left + variable margin_top + variable printargs + array set printargs {} + + # Multiple utility procedures for printing text based on the + # C printer primitives. + + # _set_dc: + # Select printer and set device context and other parameters + # for print job. + # + proc _set_dc {} { + variable printargs + variable printer_name + variable paper_width + variable paper_height + variable dpi_x + variable dpi_y + variable copies + + #First, we select the printer. + _selectprinter + + #Next, set values. Some are taken from the printer, + #some are sane defaults. + + if {[info exists printer_name] && $printer_name ne ""} { + set printargs(hDC) $printer_name + set printargs(pw) $paper_width + set printargs(pl) $paper_height + set printargs(lm) 1000 + set printargs(tm) 1000 + set printargs(rm) 1000 + set printargs(bm) 1000 + set printargs(resx) $dpi_x + set printargs(resy) $dpi_y + set printargs(copies) $copies + set printargs(resolution) [list $dpi_x $dpi_y] + } + } + + # _print_data + # This function prints multiple-page files, using a line-oriented + # function, taking advantage of knowing the character widths. + # Arguments: + # data - Text data for printing + # breaklines - If non-zero, keep newlines in the string as + # newlines in the output. + # font - Font for printing + proc _print_data {data {breaklines 1} {font ""}} { + variable printargs + variable printer_name + + _set_dc + + if {![info exists printer_name]} { + return + } + + if {$font eq ""} { + _gdi characters $printargs(hDC) -array printcharwid + } else { + _gdi characters $printargs(hDC) -font $font -array printcharwid + } + set pagewid [expr {($printargs(pw) - $printargs(rm) ) / 1000 * $printargs(resx)}] + set pagehgt [expr {($printargs(pl) - $printargs(bm) ) / 1000 * $printargs(resy)}] + set totallen [string length $data] + set curlen 0 + set curhgt [expr {$printargs(tm) * $printargs(resy) / 1000}] + + _opendoc + _openpage + + while {$curlen < $totallen} { + set linestring [string range $data $curlen end] + if {$breaklines} { + set endind [string first "\n" $linestring] + if {$endind >= 0} { + set linestring [string range $linestring 0 $endind] + # handle blank lines.... + if {$linestring eq ""} { + set linestring " " + } + } + } + + set result [_print_page_nextline $linestring \ + printcharwid printargs $curhgt $font] + incr curlen [lindex $result 0] + incr curhgt [lindex $result 1] + if {$curhgt + [lindex $result 1] > $pagehgt} { + _closepage + _openpage + set curhgt [expr {$printargs(tm) * $printargs(resy) / 1000}] + } + } + + _closepage + _closedoc + } + + # _print_file + # This function prints multiple-page files + # It will either break lines or just let them run over the + # margins (and thus truncate). + # The font argument is JUST the font name, not any additional + # arguments. + # Arguments: + # filename - File to open for printing + # breaklines - 1 to break lines as done on input, 0 to ignore newlines + # font - Optional arguments to supply to the text command + proc _print_file {filename {breaklines 1} {font ""}} { + set fn [open $filename r] + set data [read $fn] + close $fn + _print_data $data $breaklines $font + } + + # _print_page_nextline + # Returns the pair "chars y" + # where chars is the number of characters printed on the line + # and y is the height of the line printed + # Arguments: + # string - Data to print + # pdata - Array of values for printer characteristics + # cdata - Array of values for character widths + # y - Y value to begin printing at + # font - if non-empty specifies a font to draw the line in + proc _print_page_nextline {string carray parray y font} { + upvar #0 $carray charwidths + upvar #0 $parray printargs + + variable printargs + + set endindex 0 + set totwidth 0 + set maxwidth [expr { + (($printargs(pw) - $printargs(rm)) / 1000) * $printargs(resx) + }] + set maxstring [string length $string] + set lm [expr {$printargs(lm) * $printargs(resx) / 1000}] + + for {set i 0} {($i < $maxstring) && ($totwidth < $maxwidth)} {incr i} { + incr totwidth $charwidths([string index $string $i]) + # set width($i) $totwidth + } + + set endindex $i + set startindex $endindex + + if {$i < $maxstring} { + # In this case, the whole data string is not used up, and we + # wish to break on a word. Since we have all the partial + # widths calculated, this should be easy. + + set endindex [expr {[string wordstart $string $endindex] - 1}] + set startindex [expr {$endindex + 1}] + + # If the line is just too long (no word breaks), print as much + # as you can.... + if {$endindex <= 1} { + set endindex $i + set startindex $i + } + } + + set txt [string trim [string range $string 0 $endindex] "\r\n"] + if {$font ne ""} { + set result [_gdi text $printargs(hDC) $lm $y \ + -anchor nw -justify left \ + -text $txt -font $font] + } else { + set result [_gdi text $printargs(hDC) $lm $y \ + -anchor nw -justify left -text $txt] + } + return "$startindex $result" + } + + # These procedures read in the canvas widget, and write all of + # its contents out to the Windows printer. + + variable option + variable vtgPrint + + proc _init_print_canvas {} { + variable option + variable vtgPrint + variable printargs + + set vtgPrint(printer.bg) white + } + + proc _is_win {} { + variable printargs + + return [info exist tk_patchLevel] + } + + # _print_widget + # Main procedure for printing a widget. Currently supports + # canvas widgets. Handles opening and closing of printer. + # Arguments: + # wid - The widget to be printed. + # printer - Flag whether to use the default printer. + # name - App name to pass to printer. + + proc _print_widget {wid {printer default} {name "Tk Print Output"}} { + variable printargs + variable printer_name + + _set_dc + + if {![info exists printer_name]} { + return + } + + _opendoc + _openpage + + # Here is where any scaling/gdi mapping should take place + # For now, scale so the dimensions of the window are sized to the + # width of the page. Scale evenly. + + # For normal windows, this may be fine--but for a canvas, one + # wants the canvas dimensions, and not the WINDOW dimensions. + if {[winfo class $wid] eq "Canvas"} { + set sc [$wid cget -scrollregion] + # if there is no scrollregion, use width and height. + if {$sc eq ""} { + set window_x [$wid cget -width] + set window_y [$wid cget -height] + } else { + set window_x [lindex $sc 2] + set window_y [lindex $sc 3] + } + } else { + set window_x [winfo width $wid] + set window_y [winfo height $wid] + } + + set printer_x [expr { + ( $printargs(pw) - $printargs(lm) - $printargs(rm) ) * + $printargs(resx) / 1000.0 + }] + set printer_y [expr { + ( $printargs(pl) - $printargs(tm) - $printargs(bm) ) * + $printargs(resy) / 1000.0 + }] + set factor_x [expr {$window_x / $printer_x}] + set factor_y [expr {$window_y / $printer_y}] + + if {$factor_x < $factor_y} { + set lo $window_y + set ph $printer_y + } else { + set lo $window_x + set ph $printer_x + } + + _gdi map $printargs(hDC) -logical $lo -physical $ph \ + -offset $printargs(resolution) + + # Handling of canvas widgets. + switch [winfo class $wid] { + Canvas { + _print_canvas $printargs(hDC) $wid + } + default { + puts "Can't print items of type [winfo class $wid]. No handler registered" + } + } + + # End printing process. + _closepage + _closedoc + } + + # _print_canvas + # Main procedure for writing canvas widget items to printer. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + proc _print_canvas {hdc cw} { + variable vtgPrint + variable printargs + + # Get information about page being printed to + # print_canvas.CalcSizing $cw + set vtgPrint(canvas.bg) [string tolower [$cw cget -background]] + + # Re-write each widget from cw to printer + foreach id [$cw find all] { + set type [$cw type $id] + if {[info commands _print_canvas.$type] eq "_print_canvas.$type"} { + _print_canvas.[$cw type $id] $printargs(hDC) $cw $id + } else { + puts "Omitting canvas item of type $type since there is no handler registered for it" + } + } + } + + # These procedures support the various canvas item types, reading the + # information about the item on the real canvas and then writing a + # similar item to the printer. + + # _print_canvas.line + # Description: + # Prints a line item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.line {hdc cw id} { + variable vtgPrint + variable printargs + + set color [_print_canvas.TransColor [$cw itemcget $id -fill]] + if {[string match $vtgPrint(printer.bg) $color]} { + return + } + + set coords [$cw coords $id] + set wdth [$cw itemcget $id -width] + set arrow [$cw itemcget $id -arrow] + set arwshp [$cw itemcget $id -arrowshape] + set dash [$cw itemcget $id -dash] + set smooth [$cw itemcget $id -smooth] + set splinesteps [$cw itemcget $id -splinesteps] + + set cmdargs {} + + if {$wdth > 1} { + lappend cmdargs -width $wdth + } + if {$dash ne ""} { + lappend cmdargs -dash $dash + } + if {$smooth ne ""} { + lappend cmdargs -smooth $smooth + } + if {$splinesteps ne ""} { + lappend cmdargs -splinesteps $splinesteps + } + + set result [_gdi line $hdc {*}$coords \ + -fill $color -arrow $arrow -arrowshape $arwshp \ + {*}$cmdargs] + if {$result ne ""} { + puts $result + } + } + + # _print_canvas.arc + # Prints a arc item. + # Args: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.arc {hdc cw id} { + variable vtgPrint + variable printargs + + set color [_print_canvas.TransColor [$cw itemcget $id -outline]] + if {[string match $vtgPrint(printer.bg) $color]} { + return + } + set coords [$cw coords $id] + set wdth [$cw itemcget $id -width] + set style [$cw itemcget $id -style] + set start [$cw itemcget $id -start] + set extent [$cw itemcget $id -extent] + set fill [$cw itemcget $id -fill] + + set cmdargs {} + if {$wdth > 1} { + lappend cmdargs -width $wdth + } + if {$fill ne ""} { + lappend cmdargs -fill $fill + } + + _gdi arc $hdc {*}$coords \ + -outline $color -style $style -start $start -extent $extent \ + {*}$cmdargs + } + + # _print_canvas.polygon + # Prints a polygon item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.polygon {hdc cw id} { + variable vtgPrint + variable printargs + + set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]] + if {$fcolor eq ""} { + set fcolor $vtgPrint(printer.bg) + } + set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]] + if {$ocolor eq ""} { + set ocolor $vtgPrint(printer.bg) + } + set coords [$cw coords $id] + set wdth [$cw itemcget $id -width] + set smooth [$cw itemcget $id -smooth] + set splinesteps [$cw itemcget $id -splinesteps] + + set cmdargs {} + if {$smooth ne ""} { + lappend cmdargs -smooth $smooth + } + if {$splinesteps ne ""} { + lappend cmdargs -splinesteps $splinesteps + } + + _gdi polygon $hdc {*}$coords \ + -width $wdth -fill $fcolor -outline $ocolor {*}$cmdargs + } + + # _print_canvas.oval + # Prints an oval item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.oval {hdc cw id} { + variable vtgPrint + + set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]] + if {$fcolor eq ""} { + set fcolor $vtgPrint(printer.bg) + } + set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]] + if {$ocolor eq ""} { + set ocolor $vtgPrint(printer.bg) + } + set coords [$cw coords $id] + set wdth [$cw itemcget $id -width] + + _gdi oval $hdc {*}$coords \ + -width $wdth -fill $fcolor -outline $ocolor + } + + # _print_canvas.rectangle + # Prints a rectangle item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.rectangle {hdc cw id} { + variable vtgPrint + + set fcolor [_print_canvas.TransColor [$cw itemcget $id -fill]] + if {$fcolor eq ""} { + set fcolor $vtgPrint(printer.bg) + } + set ocolor [_print_canvas.TransColor [$cw itemcget $id -outline]] + if {$ocolor eq ""} { + set ocolor $vtgPrint(printer.bg) + } + set coords [$cw coords $id] + set wdth [$cw itemcget $id -width] + + _gdi rectangle $hdc {*}$coords \ + -width $wdth -fill $fcolor -outline $ocolor + } + + # _print_canvas.text + # Prints a text item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.text {hdc cw id} { + variable vtgPrint + variable printargs + + set color [_print_canvas.TransColor [$cw itemcget $id -fill]] + # if {"white" eq [string tolower $color]} {return} + # set color black + set txt [$cw itemcget $id -text] + if {$txt eq ""} { + return + } + set coords [$cw coords $id] + set anchr [$cw itemcget $id -anchor] + + set bbox [$cw bbox $id] + set wdth [expr {[lindex $bbox 2] - [lindex $bbox 0]}] + + set just [$cw itemcget $id -justify] + + # Get the real canvas font info and create a compatible font, + # suitable for printer name extraction. + set font [font create {*}[font actual [$cw itemcget $id -font]]] + + # Just get the name and family, or some of the _gdi commands will + # fail. + set font [list [font configure $font -family] \ + -[font configure $font -size]] + + _gdi text $hdc {*}$coords \ + -fill $color -text $txt -font $font \ + -anchor $anchr -width $wdth -justify $just + } + + # _print_canvas.image + # Prints an image item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.image {hdc cw id} { + # First, we have to get the image name. + set imagename [$cw itemcget $id -image] + + # Now we get the size. + set wid [image width $imagename] + set hgt [image height $imagename] + + # Next, we get the location and anchor + set anchor [$cw itemcget $id -anchor] + set coords [$cw coords $id] + + _gdi photo $hdc -destination $coords -photo $imagename + } + + # _print_canvas.bitmap + # Prints a bitmap item. + # Arguments: + # hdc - The printer handle. + # cw - The canvas widget. + # id - The id of the canvas item. + proc _print_canvas.bitmap {hdc cw id} { + variable option + variable vtgPrint + + # First, we have to get the bitmap name. + set imagename [$cw itemcget $id -image] + + # Now we get the size. + set wid [image width $imagename] + set hgt [image height $imagename] + + #Next, we get the location and anchor. + set anchor [$cw itemcget $id -anchor] + set coords [$cw coords $id] + + # Since the GDI commands don't yet support images and bitmaps, + # and since this represents a rendered bitmap, we CAN use + # copybits IF we create a new temporary toplevel to hold the beast. + # If this is too ugly, change the option! + + if {[info exist option(use_copybits)]} { + set firstcase $option(use_copybits) + } else { + set firstcase 0 + } + if {$firstcase > 0} { + set tl [toplevel .tmptop[expr {int( rand() * 65535 )}] \ + -height $hgt -width $wid \ + -background $vtgPrint(canvas.bg)] + canvas $tl.canvas -width $wid -height $hgt + $tl.canvas create image 0 0 -image $imagename -anchor nw + pack $tl.canvas -side left -expand false -fill none + tkwait visibility $tl.canvas + update + set srccoords [list 0 0 [expr {$wid - 1}] [expr {$hgt - 1}]] + set dstcoords [list [lindex $coords 0] [lindex $coords 1] [expr {$wid - 1}] [expr {$hgt - 1}]] + _gdi copybits $hdc -window $tl -client \ + -source $srccoords -destination $dstcoords + destroy $tl + } else { + _gdi bitmap $hdc {*}$coords \ + -anchor $anchor -bitmap $imagename + } + } + + # These procedures transform attribute setting from the real + # canvas to the appropriate setting for printing to paper. + + # _print_canvas.TransColor + # Does the actual transformation of colors from the + # canvas widget to paper. + # Arguments: + # color - The color value to be transformed. + proc _print_canvas.TransColor {color} { + variable vtgPrint + variable printargs + + switch [string toupper $color] { + $vtgPrint(canvas.bg) {return $vtgPrint(printer.bg)} + } + return $color + } + + # Initialize all the variables once. + _init_print_canvas + } + #end win32 procedures + + #begin X11 procedures + + # X11 procedures wrap standard Unix shell commands such as lp/lpr and + # lpstat for printing. Some output configuration that on other platforms + # is managed through the printer driver/dialog is configured through the + # canvas postscript command. + + if {[tk windowingsystem] eq "x11"} { + variable printcmd "" + variable printlist {} + variable choosepaper + variable chooseprinter {} + variable p + + # _setprintenv + # Set the print environtment - print command, and list of printers. + # Arguments: + # none. + + proc _setprintenv {} { + variable printcmd + variable printlist + + #Test for existence of lpstat command to obtain list of printers. Return error + #if not found. + + catch {exec lpstat -a} msg + set notfound "command not found" + if {[string first $notfound $msg] >= 0} { + error "Unable to obtain list of printers. Please install the CUPS package \ + for your system." + return + } + set notfound "No destinations added" + if {[string first $notfound $msg] >= 0} { + error "Please check or update your CUPS installation." + return + } + + # Select print command. We prefer lpr, but will fall back to lp if + # necessary. + if {[auto_execok lpr] ne ""} { + set printcmd lpr + } else { + set printcmd lp + } + + #Build list of printers. + set printdata [exec lpstat -a] + foreach item [split $printdata \n] { + lappend printlist [lindex [split $item] 0] + } + } + + # _print + # Main printer dialog. Select printer, set options, and + # fire print command. + # Arguments: + # w - widget with contents to print. + # + + proc _print {w} { + variable printlist + variable printcmd + variable chooseprinter + variable printcopies + variable printorientation + variable choosepaper + variable color + variable p + variable zoomnumber + + _setprintenv + + set chooseprinter [lindex $printlist 0] + + set p ._print + catch {destroy $p} + + toplevel $p + wm title $p "Print" + wm resizable $p 0 0 + + frame $p.frame -padx 10 -pady 10 + pack $p.frame -fill x -expand no + + #The main dialog + frame $p.frame.printframe -padx 5 -pady 5 + pack $p.frame.printframe -side top -fill x -expand no + + label $p.frame.printframe.printlabel -text [mc "Printer"] + ttk::combobox $p.frame.printframe.mb \ + -textvariable [namespace which -variable chooseprinter] \ + -state readonly -values [lsort -unique $printlist] + pack $p.frame.printframe.printlabel $p.frame.printframe.mb \ + -side left -fill x -expand no + + bind $p.frame.printframe.mb <> { + set chooseprinter {$p.frame.printframe.mb get} + } + + set paperlist [list [mc Letter] [mc Legal] [mc A4]] + set colorlist [list [mc Grayscale] [mc RGB]] + + #Initialize with sane defaults. + set printcopies 1 + set choosepaper [mc A4] + set color [mc RGB] + set printorientation portrait + + set percentlist {100 90 80 70 60 50 40 30 20 10} + + #Base widgets to load. + labelframe $p.frame.copyframe -text [mc "Options"] -padx 5 -pady 5 + pack $p.frame.copyframe -fill x -expand no + + frame $p.frame.copyframe.l -padx 5 -pady 5 + pack $p.frame.copyframe.l -side top -fill x -expand no + + label $p.frame.copyframe.l.copylabel -text [mc "Copies"] + spinbox $p.frame.copyframe.l.field -from 1 -to 1000 \ + -textvariable [namespace which -variable printcopies] -width 5 + + pack $p.frame.copyframe.l.copylabel $p.frame.copyframe.l.field \ + -side left -fill x -expand no + + set printcopies [$p.frame.copyframe.l.field get] + + frame $p.frame.copyframe.r -padx 5 -pady 5 + pack $p.frame.copyframe.r -fill x -expand no + + label $p.frame.copyframe.r.paper -text [mc "Paper"] + tk_optionMenu $p.frame.copyframe.r.menu \ + [namespace which -variable choosepaper] \ + {*}$paperlist + + pack $p.frame.copyframe.r.paper $p.frame.copyframe.r.menu \ + -side left -fill x -expand no + + #Widgets with additional options for canvas output. + if {[winfo class $w] eq "Canvas"} { + + frame $p.frame.copyframe.z -padx 5 -pady 5 + pack $p.frame.copyframe.z -fill x -expand no + + label $p.frame.copyframe.z.zlabel -text [mc "Scale"] + tk_optionMenu $p.frame.copyframe.z.zentry \ + [namespace which -variable zoomnumber] \ + {*}$percentlist + + pack $p.frame.copyframe.z.zlabel $p.frame.copyframe.z.zentry \ + -side left -fill x -expand no + + frame $p.frame.copyframe.orient -padx 5 -pady 5 + pack $p.frame.copyframe.orient -fill x -expand no + + label $p.frame.copyframe.orient.text -text [mc "Orientation"] + radiobutton $p.frame.copyframe.orient.v -text [mc "Portrait"] \ + -value portrait -compound left \ + -variable [namespace which -variable printorientation] + radiobutton $p.frame.copyframe.orient.h -text [mc "Landscape"] \ + -value landscape -compound left \ + -variable [namespace which -variable printorientation] + + pack $p.frame.copyframe.orient.text \ + $p.frame.copyframe.orient.v $p.frame.copyframe.orient.h \ + -side left -fill x -expand no + + frame $p.frame.copyframe.c -padx 5 -pady 5 + pack $p.frame.copyframe.c -fill x -expand no + + label $p.frame.copyframe.c.l -text [mc "Output"] + tk_optionMenu $p.frame.copyframe.c.c \ + [namespace which -variable color] \ + {*}$colorlist + pack $p.frame.copyframe.c.l $p.frame.copyframe.c.c -side left \ + -fill x -expand no + } + + #Build rest of GUI. + frame $p.frame.buttonframe + pack $p.frame.buttonframe -fill x -expand no -side bottom + + button $p.frame.buttonframe.printbutton -text [mc "Print"] \ + -command [namespace code [list _runprint $w]] + button $p.frame.buttonframe.cancel -text [mc "Cancel"] \ + -command {destroy ._print} + + pack $p.frame.buttonframe.printbutton $p.frame.buttonframe.cancel \ + -side right -fill x -expand no + #Center the window as a dialog. + ::tk::PlaceWindow $p + } + + # _runprint - + # Execute the print command--print the file. + # Arguments: + # w - widget with contents to print. + # + proc _runprint {w} { + variable printlist + variable printcmd + variable choosepaper + variable chooseprinter + variable color + variable printcopies + variable printorientation + variable zoomnumber + variable p + + #First, generate print file. + + if {[winfo class $w] eq "Text"} { + set file [makeTempFile tk_text.txt [$w get 1.0 end]] + } + + if {[winfo class $w] eq "Canvas"} { + if {$color eq [mc "RGB"]} { + set colormode color + } else { + set colormode gray + } + + if {$printorientation eq "landscape"} { + set willrotate "1" + } else { + set willrotate "0" + } + + #Scale based on size of widget, not size of paper. + set printwidth [expr {$zoomnumber / 100.00 * [winfo width $w]}] + set file [makeTempFile tk_canvas.ps] + $w postscript -file $file -colormode $colormode \ + -rotate $willrotate -pagewidth $printwidth + } + + #Build list of args to pass to print command. + + set printargs {} + set printcopies [$p.frame.copyframe.l.field get] + if {$printcmd eq "lpr"} { + lappend printargs -P $chooseprinter -# $printcopies + } else { + lappend printargs -d $chooseprinter -n $printcopies + } + + after 500 + exec $printcmd {*}$printargs -o PageSize=$choosepaper $file + + after 500 + destroy ._print + } + } + #end X11 procedures + + #begin macOS Aqua procedures + if {[tk windowingsystem] eq "aqua"} { + # makePDF - + # Convert a file to PDF + # Arguments: + # inFilename - file containing the data to convert; format is + # autodetected. + # outFilename - base for filename to write to; conventionally should + # have .pdf as suffix + # Returns: + # The full pathname of the generated PDF. + # + proc makePDF {inFilename outFilename} { + set out [::tk::print::makeTempFile $outFilename] + try { + exec /usr/sbin/cupsfilter $inFilename > $out + } trap NONE {msg} { + # cupsfilter produces a lot of debugging output, which we + # don't want. + regsub -all -line {^(?:DEBUG|INFO):.*$} $msg "" msg + set msg [string trimleft [regsub -all {\n+} $msg "\n"] "\n"] + if {$msg ne ""} { + # Lines should be prefixed with WARN or ERROR now + puts $msg + } + } + return $out + } + } + #end macOS Aqua procedures + + namespace export canvas text + namespace ensemble create +} + +# tk print -- +# This procedure prints the canvas and text widgets using platform- +# native API's. +# Arguments: +# w: Widget to print. +proc ::tk::print {w} { + switch [winfo class $w],[tk windowingsystem] { + "Canvas,win32" { + tailcall ::tk::print::_print_widget $w 0 "Tk Print Output" + } + "Canvas,x11" { + tailcall ::tk::print::_print $w + } + "Canvas,aqua" { + set psfile [::tk::print::makeTempFile tk_canvas.ps] + try { + $w postscript -file $psfile + set printfile [::tk::print::makePDF $psfile tk_canvas.pdf] + ::tk::print::_print $printfile + } finally { + file delete $psfile + } + } + + "Text,win32" { + tailcall ::tk::print::_print_data [$w get 1.0 end] 1 {Arial 12} + } + "Text,x11" { + tailcall ::tk::print::_print $w + } + "Text,aqua" { + set txtfile [::tk::print::makeTempFile tk_text.txt [$w get 1.0 end]] + try { + set printfile [::tk::print::makePDF $txtfile tk_text.pdf] + ::tk::print::_print $printfile + } finally { + file delete $txtfile + } + } + + default { + return -code error -errorcode {TK PRINT CLASS_UNSUPPORTED} \ + "widgets of class [winfo class $w] are not supported on\ + this platform" + } + } +} + +#Add this command to the tk command ensemble: tk print +#Thanks to Christian Gollwitzer for the guidance here +namespace ensemble configure tk -map \ + [dict merge [namespace ensemble configure tk -map] \ + {print ::tk::print}] + +return + +# Local Variables: +# mode: tcl +# fill-column: 78 +# End: Index: library/scrlbar.tcl ================================================================== --- library/scrlbar.tcl +++ library/scrlbar.tcl @@ -128,14 +128,14 @@ tk::ScrollToPos %W 1 } } bind Scrollbar { - tk::ScrollByUnits %W hv %D -30.0 + tk::ScrollByUnits %W hv %D -40.0 } bind Scrollbar { - tk::ScrollByUnits %W hv %D -3.0 + tk::ScrollByUnits %W hv %D -12.0 } # tk::ScrollButtonDown -- # This procedure is invoked when a button is pressed in a scrollbar. # It changes the way the scrollbar is displayed and takes actions Index: library/spinbox.tcl ================================================================== --- library/spinbox.tcl +++ library/spinbox.tcl @@ -127,21 +127,21 @@ bind Spinbox <> { %W invoke buttondown } bind Spinbox <> { - ::tk::EntrySetCursor %W [expr {[%W index insert] - 1}] + ::tk::EntrySetCursor %W [%W index insert]-1 } bind Spinbox <> { - ::tk::EntrySetCursor %W [expr {[%W index insert] + 1}] + ::tk::EntrySetCursor %W [%W index insert]+1 } bind Spinbox <> { - ::tk::EntryKeySelect %W [expr {[%W index insert] - 1}] + ::tk::EntryKeySelect %W [%W index insert]-1 ::tk::EntrySeeInsert %W } bind Spinbox <> { - ::tk::EntryKeySelect %W [expr {[%W index insert] + 1}] + ::tk::EntryKeySelect %W [%W index insert]+1 ::tk::EntrySeeInsert %W } bind Spinbox <> { ::tk::EntrySetCursor %W [::tk::EntryPreviousWord %W insert] } @@ -216,13 +216,11 @@ bind Spinbox {# nothing} bind Spinbox {# nothing} bind Spinbox {# nothing} bind Spinbox {# nothing} bind Spinbox {# nothing} -if {[tk windowingsystem] eq "aqua"} { - bind Spinbox {# nothing} -} +bind Spinbox {# nothing} # On Windows, paste is done using Shift-Insert. Shift-Insert already # generates the <> event, so we don't need to do anything here. if {[tk windowingsystem] ne "win32"} { bind Spinbox { ADDED library/systray.tcl Index: library/systray.tcl ================================================================== --- /dev/null +++ library/systray.tcl @@ -0,0 +1,328 @@ +# systray.tcl -- + +# This file defines the 'tk systray' command for icon display and manipulation +# in the system tray on X11, Windows, and macOS, and the 'tk sysnotify' command +# for system alerts on each platform. It implements an abstraction layer that +# presents a consistent API across the three platforms. + +# Copyright © 2020 Kevin Walzer/WordTech Communications LLC. +# Copyright © 2020 Eric Boudaillier. +# Copyright © 2020 Francois Vogel. +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. + +# Pure-Tcl system tooltip window for use with system tray icon if native +# implementation not available. + +namespace eval ::tk::systray { + variable _created 0 + variable _options {-image "" -text "" -button1 "" -button3 ""} + variable _current {} + variable _ico + + proc _balloon {w help} { + bind $w "after 1000 [list ::tk::systray::_balloon_show %W [list $help]]" + bind $w "destroy %W._balloon" + } + + proc _balloon_show {w arg} { + if {[winfo containing {*}[winfo pointerxy .]] ne $w} { + return + } + set top $w._balloon + catch {destroy $top} + toplevel $top -bg black + wm overrideredirect $top 1 + if {[tk windowingsystem] eq "aqua"} { + ::tk::unsupported::MacWindowStyle style $top help none + } + pack [message $top._txt -aspect 10000 -text $arg] + set wmx [winfo rootx $w] + set wmy [expr {[winfo rooty $w] + [winfo height $w]}] + wm geometry $top [winfo reqwidth $top._txt]x[winfo reqheight $top._txt]+$wmx+$wmy + raise $top + } + + proc _win_callback {msg} { + variable _current + # The API at the Tk level does not feature bindings to double clicks. Whatever + # the speed the user clicks with, he expects the single click binding to fire. + # Therefore we need to bind to both WM_*BUTTONDOWN and to WM_*BUTTONDBLCLK. + switch -exact -- $msg { + WM_LBUTTONDOWN - WM_LBUTTONDBLCLK { + uplevel #0 [dict get $_current -button1] + } + WM_RBUTTONDOWN - WM_RBUTTONDBLCLK { + uplevel #0 [dict get $_current -button3] + } + } + } + + namespace export create configure destroy + namespace ensemble create +} + + +# Pure-Tcl system notification window for use if native implementation not available. +namespace eval ::tk::sysnotify:: { + + proc _notifywindow {title msg} { + catch {destroy ._notify} + set w [toplevel ._notify] + if {[tk windowingsystem] eq "aqua"} { + ::tk::unsupported::MacWindowStyle style $w utility {hud closeBox resizable} + wm title $w "Alert" + } + if {[tk windowingsystem] eq "win32"} { + wm attributes $w -toolwindow true + wm title $w "Alert" + } + label $w.l -bg gray30 -fg white -image ::tk::icons::information + pack $w.l -fill both -expand yes -side left + message $w.message -aspect 150 -bg gray30 -fg white -aspect 150 -text $title\n\n$msg -width 280 + pack $w.message -side right -fill both -expand yes + if {[tk windowingsystem] eq "x11"} { + wm overrideredirect $w true + } + wm attributes $w -alpha 0.0 + set xpos [expr {[winfo screenwidth $w] - 325}] + wm geometry $w +$xpos+30 + ::tk::sysnotify::_fade_in $w + after 3000 ::tk::sysnotify::_fade_out $w + } + + #Fade and destroy window. + proc _fade_out {w} { + catch { + set prev_degree [wm attributes $w -alpha] + set new_degree [expr {$prev_degree - 0.05}] + set current_degree [wm attributes $w -alpha $new_degree] + if {$new_degree > 0.0 && $new_degree != $prev_degree} { + after 10 [list ::tk::sysnotify::_fade_out $w] + } else { + destroy $w + } + } + } + + #Fade the window into view. + proc _fade_in {w} { + catch { + raise $w + wm attributes $w -topmost 1 + set prev_degree [wm attributes $w -alpha] + set new_degree [expr {$prev_degree + 0.05}] + set current_degree [wm attributes $w -alpha $new_degree] + focus -force $w + if {$new_degree < 0.9 && $new_degree != $prev_degree} { + after 10 [list ::tk::sysnotify::_fade_in $w] + } + } + } + namespace export * +} + + +# tk systray -- +# This procedure creates an icon display in the platform-specific system tray. +# +# Subcommands: +# +# create - create systray icon. +# Arguments: +# -image - Tk image to display. +# -text - string to display in tooltip over image. +# -button1 - Tcl proc to invoke on event. +# -button3 - Tcl proc to invoke on event. +# +# configure - change one of the systray properties. +# Arguments (Any or all can be called): +# -image - Tk image to update. +# -text - string to update. +# -button1 - Tcl proc to change for event. +# -button3 - Tcl proc to change for event. +# +# destroy - destroy systray icon. +# Arguments: +# none. +proc ::tk::systray::create {args} { + variable _created + variable _options + variable _current + variable _ico + + if {$_created} { + return -code error -errorcode {TK SYSTRAY CREATE} "only one system tray icon supported per interpeter" + } + _check_options $args 0 + if {![dict exists $args -image]} { + return -code error -errorcode {TK SYSTRAY CREATE} "missing required option \"-image\"" + } + set values [dict merge $_options $args] + try { + switch -- [tk windowingsystem] { + "win32" { + set _ico [_systray add -image [dict get $values -image] \ + -text [dict get $values -text] \ + -callback [list ::tk::systray::_win_callback %m]] + } + "x11" { + _systray ._tray -image [dict get $values -image] -visible true + _balloon ._tray [dict get $values -text] + bind ._tray [dict get $values -button1] + bind ._tray [dict get $values -button3] + } + "aqua" { + _systray create [dict get $values -image] [dict get $values -text] \ + [dict get $values -button1] [dict get $values -button3] + } + } + } on ok {} { + set _current $values + set _created 1 + return + } on error {msg opts} { + return -code error -errorcode [dict get $opts -errorcode] $msg + } +} + +# Modify the systray icon. +proc ::tk::systray::configure {args} { + variable _created + variable _options + variable _current + variable _ico + + if {!$_created} { + return -code error -errorcode {TK SYSTRAY CREATE} "systray not created" + } + _check_options $args 1 + if {[llength $args] == 0} { + return $_current + } elseif {[llength $args] == 1} { + return [dict get $_current [lindex $args 0]] + } + set values [dict merge $_current $args] + try { + switch -- [tk windowingsystem] { + "win32" { + if {[dict exists $args -image]} { + _systray modify $_ico -image [dict get $args -image] + } + if {[dict exists $args -text]} { + _systray modify $_ico -text [dict get $args -text] + } + } + "x11" { + if {[dict exists $args -image]} { + ._tray configure -image [dict get $args -image] + } + if {[dict exists $args -text]} { + _balloon ._tray [dict get $args -text] + } + if {[dict exists $args -button1]} { + bind ._tray [dict get $args -button1] + } + if {[dict exists $args -button3]} { + bind ._tray [dict get $args -button3] + } + } + "aqua" { + foreach {key opt} {image -image text \ + -text b1_callback -button1 b3_callback -button3} { + if {[dict exists $args $opt]} { + _systray modify $key [dict get $args $opt] + } + } + } + } + } on ok {} { + set _current $values + return + } on error {msg opts} { + return -code error -errorcode [dict get $opts -errorcode] $msg + } +} + + +# Remove the systray icon. +proc ::tk::systray::destroy {} { + variable _created + variable _current + variable _ico + + if {!$_created} { + return -code error -errorcode {TK SYSTRAY DESTROY} "systray not created" + } + switch -- [tk windowingsystem] { + "win32" { + _systray delete $_ico + set _ico "" + } + "x11" { + ::destroy ._tray + } + "aqua" { + _systray destroy + } + } + set _created 0 + set _current {} + return +} + +# Check systray options +proc ::tk::systray::_check_options {argsList singleOk} { + variable _options + + set len [llength $argsList] + while {[llength $argsList] > 0} { + set opt [lindex $argsList 0] + if {![dict exists $_options $opt]} { + tailcall return -code error -errorcode {TK SYSTRAY OPTION} \ + "unknown option \"$opt\": must be -image, -text, -button1 or -button3" + } + if {[llength $argsList] == 1 && !($len == 1 && $singleOk)} { + tailcall return -code error -errorcode {TK SYSTRAY OPTION} \ + "missing value for option \"$opt\"" + } + set argsList [lrange $argsList 2 end] + } +} + +# tk sysnotify -- +# This procedure implements a platform-specific system notification alert. +# +# Arguments: +# title - main text of alert. +# message - body text of alert. + +proc ::tk::sysnotify::sysnotify {title message} { + + switch -- [tk windowingsystem] { + "win32" { + if {!$::tk::systray::_created} { + error "must create a system tray icon with the \"tk systray\" command first" + } + _sysnotify notify $::tk::systray::_ico $title $message + } + "x11" { + if {[info commands ::tk::sysnotify::_sysnotify] eq ""} { + _notifywindow $title $message + } else { + _sysnotify $title $message + } + } + "aqua" { + _sysnotify $title $message + } + } + return +} + +#Add these commands to the tk command ensemble: tk systray, tk sysnotify +#Thanks to Christian Gollwitzer for the guidance here +namespace ensemble configure tk -map \ + [dict merge [namespace ensemble configure tk -map] \ + {systray ::tk::systray sysnotify ::tk::sysnotify::sysnotify}] Index: library/tearoff.tcl ================================================================== --- library/tearoff.tcl +++ library/tearoff.tcl @@ -133,11 +133,11 @@ } lappend cmd [lindex $option 0] [lindex $option 4] } eval $cmd set last [$src index last] - if {$last eq "none"} { + if {$last < 0} { return } for {set i [$src cget -tearoff]} {$i <= $last} {incr i} { set cmd [list $dst add [$src type $i]] foreach option [$src entryconfigure $i] { Index: library/text.tcl ================================================================== --- library/text.tcl +++ library/text.tcl @@ -3,11 +3,11 @@ # This file defines the default bindings for Tk text widgets and provides # procedures that help in implementing the bindings. # # Copyright © 1992-1994 The Regents of the University of California. # Copyright © 1994-1997 Sun Microsystems, Inc. -# Copyright © 1998 by Scriptics Corporation. +# Copyright © 1998 Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # @@ -304,13 +304,11 @@ bind Text {# nothing } bind Text {# nothing} bind Text {# nothing} bind Text {# nothing} bind Text {# nothing} -if {[tk windowingsystem] eq "aqua"} { - bind Text {# nothing} -} +bind Text {# nothing} # Additional emacs-like bindings: bind Text { if {!$tk_strictMotif && [%W compare end != insert+1c]} { @@ -395,23 +393,37 @@ bind Text <> { dict set ::tk::Priv(IMETextMark) "%W" [%W index insert] } bind Text <> { - if { [catch {dict get $::tk::Priv(IMETextMark) "%W"} mark] } { - bell - } else { - %W tag add IMEmarkedtext $mark insert - %W tag configure IMEmarkedtext -underline on - } + ::tk::TextEndIMEMarkedText %W } bind Text <> { %W delete IMEmarkedtext.first IMEmarkedtext.last } bind Text <> { %W delete insert-1c } + +# ::tk::TextEndIMEMarkedText -- +# +# Handles input method text marking in a text widget. +# +# Arguments: +# w - The text widget + +proc ::tk::TextEndIMEMarkedText {w} { + variable Priv + if {[catch { + set mark [dict get $Priv(IMETextMark) $w] + }]} { + bell + return + } + $w tag add IMEmarkedtext $mark insert + $w tag configure IMEmarkedtext -underline on +} # Macintosh only bindings: if {[tk windowingsystem] eq "aqua"} { bind Text { @@ -440,20 +452,20 @@ } } set ::tk::Priv(prevPos) {} bind Text { - tk::MouseWheel %W y %D -3.0 pixels + tk::MouseWheel %W y %D -4.0 pixels } bind Text { - tk::MouseWheel %W y %D -0.3 pixels + tk::MouseWheel %W y %D -1.2 pixels } bind Text { - tk::MouseWheel %W x %D -3.0 pixels + tk::MouseWheel %W x %D -4.0 pixels } bind Text { - tk::MouseWheel %W x %D -0.3 pixels + tk::MouseWheel %W x %D -1.2 pixels } # ::tk::TextClosestGap -- # Given x and y coordinates, this procedure finds the closest boundary # between characters to the given coordinates and returns the index Index: library/tk.tcl ================================================================== --- library/tk.tcl +++ library/tk.tcl @@ -9,11 +9,11 @@ # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # Verify that we have Tk binary and script components from the same release -package require -exact Tk 8.7a4 +package require -exact tk 8.7a6 # Create a ::tk namespace namespace eval ::tk { # Set up the msgcat commands namespace eval msgcat { @@ -377,11 +377,11 @@ event add <> event add <> # On Darwin/Aqua, buttons from left to right are 1,3,2. On Darwin/X11 with recent # XQuartz as the X server, they are 1,2,3; other X servers may differ. - event add <> + event add <> event add <> event add <> event add <> event add <> event add <> @@ -424,11 +424,11 @@ event add <> event add <> event add <> event add <> - event add <> + event add <> event add <> event add <> event add <> event add <> event add <> @@ -455,11 +455,11 @@ event add <> event add <> event add <> # Official bindings - # See http://support.apple.com/kb/HT1343 + # See https://support.apple.com/en-us/HT201236 event add <> event add <> event add <> event add <> event add <> @@ -495,18 +495,21 @@ proc ::tk::SourceLibFile {file} { namespace eval :: [list source -encoding utf-8 [file join $::tk_library $file.tcl]] } namespace eval ::tk { SourceLibFile icons + SourceLibFile iconbadges SourceLibFile button SourceLibFile entry SourceLibFile listbox SourceLibFile menu SourceLibFile panedwindow + SourceLibFile print SourceLibFile scale SourceLibFile scrlbar SourceLibFile spinbox + SourceLibFile systray SourceLibFile text } } # ---------------------------------------------------------------------- @@ -696,10 +699,15 @@ } proc ::tk::mac::DoScriptText {script} { uplevel #0 $script eval $script } + #This procedure is required to silence warnings generated + #by inline AppleScript execution. + proc ::tk::mac::GetDynamicSdef {} { + puts "" + } } # Create a dictionary to store the starting index of the IME marked # text in an Entry or Text widget. Index: library/ttk/aquaTheme.tcl ================================================================== --- library/ttk/aquaTheme.tcl +++ library/ttk/aquaTheme.tcl @@ -33,25 +33,48 @@ pressed white {alternate !pressed !background} white} ttk::style configure TMenubutton -anchor center -padding {2 0 0 2} ttk::style configure Toolbutton -anchor center + # For Entry, Combobox and Spinbox widgets the selected text background + # is the "Highlight color" selected in preferences when the widget + # has focus. It is a gray color when the widget does not have focus or + # the window does not have focus. (The background state implies !focus + # so we only need to specify !focus.) + # Entry ttk::style configure TEntry \ -foreground systemTextColor \ -background systemTextBackgroundColor ttk::style map TEntry \ -foreground { disabled systemDisabledControlTextColor } \ - -selectforeground { - background systemTextColor + -selectbackground { + !focus systemUnemphasizedSelectedTextBackgroundColor + } + + # Combobox: + ttk::style map TCombobox \ + -foreground { + disabled systemDisabledControlTextColor } \ -selectbackground { - background systemTextBackgroundColor + !focus systemUnemphasizedSelectedTextBackgroundColor } + # Spinbox + ttk::style configure TSpinbox \ + -foreground systemTextColor \ + -background systemTextBackgroundColor + ttk::style map TSpinbox \ + -foreground { + disabled systemDisabledControlTextColor + } \ + -selectbackground { + !focus systemUnemphasizedSelectedTextBackgroundColor + } # Workaround for #1100117: # Actually, on Aqua we probably shouldn't stipple images in # disabled buttons even if it did work... ttk::style configure . -stipple {} @@ -65,44 +88,10 @@ -foreground { background systemControlTextColor disabled systemDisabledControlTextColor selected systemSelectedTabTextColor} - # Combobox: - ttk::style configure TCombobox \ - -foreground systemTextColor \ - -background systemTransparent - ttk::style map TCombobox \ - -foreground { - disabled systemDisabledControlTextColor - } \ - -selectforeground { - background systemTextColor - } \ - -selectbackground { - background systemTransparent - } - - # Spinbox - ttk::style configure TSpinbox \ - -foreground systemTextColor \ - -background systemTextBackgroundColor \ - -selectforeground systemSelectedTextColor \ - -selectbackground systemSelectedTextBackgroundColor - ttk::style map TSpinbox \ - -foreground { - disabled systemDisabledControlTextColor - } \ - -selectforeground { - !active systemTextColor - } \ - -selectbackground { - !active systemTextBackgroundColor - !focus systemTextBackgroundColor - focus systemSelectedTextBackgroundColor - } - # Treeview: ttk::style configure Heading \ -font TkHeadingFont \ -foreground systemTextColor \ -background systemWindowBackgroundColor @@ -114,11 +103,11 @@ -background { selected systemSelectedTextBackgroundColor } # Enable animation for ttk::progressbar widget: - ttk::style configure TProgressbar -period 100 -maxphase 255 + ttk::style configure TProgressbar -period 100 -maxphase 120 # For Aqua, labelframe labels should appear outside the border, # with a 14 pixel inset and 4 pixels spacing between border and label # (ref: Apple Human Interface Guidelines / Controls / Grouping Controls) # Index: library/ttk/button.tcl ================================================================== --- library/ttk/button.tcl +++ library/ttk/button.tcl @@ -40,11 +40,11 @@ # ...plus a few more: bind TRadiobutton { ttk::button::RadioTraverse %W -1 } bind TRadiobutton { ttk::button::RadioTraverse %W +1 } -# bind TCheckbutton { %W select } +# bind TCheckbutton <+> { %W select } # bind TCheckbutton { %W deselect } # activate -- # Simulate a button press: temporarily set the state to 'pressed', # then invoke the button. Index: library/ttk/combobox.tcl ================================================================== --- library/ttk/combobox.tcl +++ library/ttk/combobox.tcl @@ -184,17 +184,20 @@ # proc ttk::combobox::Scroll {cb dir {factor 1.0}} { $cb instate disabled { return } set max [llength [$cb cget -values]] set current [$cb current] - set d [expr {round($dir/factor)}] - if {$d == 0 && $dir != 0} { - if {$dir > 0} {set d 1} else {set d -1} + if {$current < 0} { + set index 0 + } else { + set d [expr {$dir/$factor}] + set index [expr {$current + int($d > 0 ? ceil($d) : floor($d))}] + if {$index >= $max} {set index [expr {$max - 1}]} + if {$index < 0} {set index 0} } - incr current $d - if {$max != 0 && $current == $current % $max} { - SelectEntry $cb $current + if {$max != 0 && $index != $current} { + SelectEntry $cb $index } } ## LBSelected $lb -- Activation binding for listbox # Set the combobox value to the currently-selected listbox value Index: library/ttk/entry.tcl ================================================================== --- library/ttk/entry.tcl +++ library/ttk/entry.tcl @@ -128,16 +128,12 @@ bind TEntry {# nothing} bind TEntry {# nothing} bind TEntry {# nothing} bind TEntry {# nothing} bind TEntry {# nothing} +bind TEntry {# nothing} -# Argh. Apparently on Windows, the NumLock modifier is interpreted -# as a Command modifier. -if {[tk windowingsystem] eq "aqua"} { - bind TEntry {# nothing} -} # Tk-on-Cocoa generates characters for these two keys. [Bug 2971663] bind TEntry <> {# nothing} bind TEntry <> {# nothing} ## Additional emacs-like bindings: @@ -162,10 +158,23 @@ %W delete [dict get $::tk::Priv(IMETextMark) "%W"] [%W index insert] } bind TEntry <> { ttk::entry::Backspace %W } + +## EndIMEMarkedText -- Handle the end of input method selection. +# +proc ::ttk::entry::EndIMEMarkedText {w} { + variable ::tk::Priv + if {[catch { + set mark [dict get $Priv(IMETextMark) $w] + }]} { + bell + return + } + $w selection range $mark insert +} ### Clipboard procedures. # ## EntrySelection -- Return the selected text of the entry. Index: library/ttk/fonts.tcl ================================================================== --- library/ttk/fonts.tcl +++ library/ttk/fonts.tcl @@ -64,90 +64,85 @@ catch {font create TkFixedFont} catch {font create TkIconFont} catch {font create TkMenuFont} catch {font create TkSmallCaptionFont} -if {!$tip145} { -variable F ;# miscellaneous platform-specific font parameters +if {!$tip145} {apply {{} { +global tcl_platform switch -- [tk windowingsystem] { win32 { # In safe interps there is no osVersion element. if {[info exists tcl_platform(osVersion)]} { if {$tcl_platform(osVersion) >= 5.0} { - set F(family) "Tahoma" + set family "Tahoma" } else { - set F(family) "MS Sans Serif" + set family "MS Sans Serif" } } else { if {[lsearch -exact [font families] Tahoma] >= 0} { - set F(family) "Tahoma" - } else { - set F(family) "MS Sans Serif" - } - } - set F(size) 8 - - font configure TkDefaultFont -family $F(family) -size $F(size) - font configure TkTextFont -family $F(family) -size $F(size) - font configure TkHeadingFont -family $F(family) -size $F(size) - font configure TkCaptionFont -family $F(family) -size $F(size) \ - -weight bold - font configure TkTooltipFont -family $F(family) -size $F(size) - font configure TkFixedFont -family Courier -size 10 - font configure TkIconFont -family $F(family) -size $F(size) - font configure TkMenuFont -family $F(family) -size $F(size) - font configure TkSmallCaptionFont -family $F(family) -size $F(size) + set family "Tahoma" + } else { + set family "MS Sans Serif" + } + } + set size 8 + + font configure TkDefaultFont -family $family -size $size + font configure TkTextFont -family $family -size $size + font configure TkHeadingFont -family $family -size $size + font configure TkCaptionFont -family $family -size $size -weight bold + font configure TkTooltipFont -family $family -size $size + font configure TkFixedFont -family Courier -size 10 + font configure TkIconFont -family $family -size $size + font configure TkMenuFont -family $family -size $size + font configure TkSmallCaptionFont -family $family -size $size } aqua { - set F(family) "Lucida Grande" - set F(fixed) "Monaco" - set F(menusize) 14 - set F(size) 13 - set F(viewsize) 12 - set F(smallsize) 11 - set F(labelsize) 10 - set F(fixedsize) 11 - - font configure TkDefaultFont -family $F(family) -size $F(size) - font configure TkTextFont -family $F(family) -size $F(size) - font configure TkHeadingFont -family $F(family) -size $F(smallsize) - font configure TkCaptionFont -family $F(family) -size $F(size) \ - -weight bold - font configure TkTooltipFont -family $F(family) -size $F(smallsize) - font configure TkFixedFont -family $F(fixed) -size $F(fixedsize) - font configure TkIconFont -family $F(family) -size $F(size) - font configure TkMenuFont -family $F(family) -size $F(menusize) - font configure TkSmallCaptionFont -family $F(family) -size $F(labelsize) + set family "Lucida Grande" + set fixed "Monaco" + set menusize 14 + set size 13 + set viewsize 12 + set smallsize 11 + set labelsize 10 + set fixedsize 11 + + font configure TkDefaultFont -family $family -size $size + font configure TkTextFont -family $family -size $size + font configure TkHeadingFont -family $family -size $smallsize + font configure TkCaptionFont -family $family -size $size -weight bold + font configure TkTooltipFont -family $family -size $smallsize + font configure TkFixedFont -family $fixed -size $fixedsize + font configure TkIconFont -family $family -size $size + font configure TkMenuFont -family $family -size $menusize + font configure TkSmallCaptionFont -family $family -size $labelsize } default - x11 { - if {![catch {tk::pkgconfig get fontsystem} F(fs)] && $F(fs) eq "xft"} { - set F(family) "sans-serif" - set F(fixed) "monospace" - } else { - set F(family) "Helvetica" - set F(fixed) "courier" - } - set F(size) 10 - set F(ttsize) 9 - set F(capsize) 12 - set F(fixedsize) 10 - - font configure TkDefaultFont -family $F(family) -size $F(size) - font configure TkTextFont -family $F(family) -size $F(size) - font configure TkHeadingFont -family $F(family) -size $F(size) \ - -weight bold - font configure TkCaptionFont -family $F(family) -size $F(capsize) \ - -weight bold - font configure TkTooltipFont -family $F(family) -size $F(ttsize) - font configure TkFixedFont -family $F(fixed) -size $F(fixedsize) - font configure TkIconFont -family $F(family) -size $F(size) - font configure TkMenuFont -family $F(family) -size $F(size) - font configure TkSmallCaptionFont -family $F(family) -size $F(ttsize) - } -} -unset -nocomplain F -} + if {![catch {tk::pkgconfig get fontsystem} fs] && $fs eq "xft"} { + set family "sans-serif" + set fixed "monospace" + } else { + set family "Helvetica" + set fixed "courier" + } + set size 10 + set ttsize 9 + set capsize 12 + set fixedsize 10 + + font configure TkDefaultFont -family $family -size $size + font configure TkTextFont -family $family -size $size + font configure TkHeadingFont -family $family -size $size -weight bold + font configure TkCaptionFont -family $family -size $capsize -weight bold + font configure TkTooltipFont -family $family -size $ttsize + font configure TkFixedFont -family $fixed -size $fixedsize + font configure TkIconFont -family $family -size $size + font configure TkMenuFont -family $family -size $size + font configure TkSmallCaptionFont -family $family -size $ttsize + } +} +} ::ttk}} } #*EOF* Index: library/ttk/menubutton.tcl ================================================================== --- library/ttk/menubutton.tcl +++ library/ttk/menubutton.tcl @@ -81,13 +81,12 @@ set bh [expr {[winfo height $mb]} + $buttonPad] set bbh [expr {[winfo height $mb]} + $bevelPad] set mw [winfo reqwidth $menu] set bw [winfo width $mb] set dF [expr {[winfo width $mb] - [winfo reqwidth $menu] - $menuPad}] - set entry "" set entry [::tk::MenuFindName $menu [$mb cget -text]] - if {$entry eq ""} { + if {$entry < 0} { set entry 0 } set x [winfo rootx $mb] set y [winfo rooty $mb] switch [$mb cget -direction] { @@ -122,29 +121,28 @@ set dF [expr {[winfo width $mb] - [winfo reqwidth $menu]}] if {[tk windowingsystem] eq "win32"} { incr mh 6 incr mw 16 } - set entry {} set entry [::tk::MenuFindName $menu [$mb cget -text]] - if {$entry eq {}} { + if {$entry < 0} { set entry 0 } set x [winfo rootx $mb] set y [winfo rooty $mb] switch [$mb cget -direction] { above { - set entry {} + set entry "" incr y -$mh # if we go offscreen to the top, show as 'below' if {$y < [winfo vrooty $mb]} { set y [expr {[winfo vrooty $mb] + [winfo rooty $mb]\ + [winfo reqheight $mb]}] } } below { - set entry {} + set entry "" incr y $bh # if we go offscreen to the bottom, show as 'above' if {($y + $mh) > ([winfo vrooty $mb] + [winfo vrootheight $mb])} { set y [expr {[winfo vrooty $mb] + [winfo vrootheight $mb] \ + [winfo rooty $mb] - $mh}] @@ -194,11 +192,11 @@ set State(oldcursor) [$mb cget -cursor] $mb state pressed $mb configure -cursor [$menu cget -cursor] foreach {x y entry} [PostPosition $mb $menu] { break } - if {$entry ne {}} { + if {$entry >= 0} { $menu post $x $y $entry } else { $menu post $x $y } tk_menuSetFocus $menu @@ -226,11 +224,11 @@ # Returns the index of the menu entry with a matching -label, # "" if not found. # proc ttk::menubutton::FindMenuEntry {menu s} { set last [$menu index last] - if {$last eq "none" || $last eq ""} { + if {$last < 0} { return "" } for {set i 0} {$i <= $last} {incr i} { if {![catch {$menu entrycget $i -label} label] && ($label eq $s)} { Index: library/ttk/notebook.tcl ================================================================== --- library/ttk/notebook.tcl +++ library/ttk/notebook.tcl @@ -14,10 +14,12 @@ catch { bind TNotebook { ttk::notebook::CycleTab %W -1; break } } bind TNotebook { ttk::notebook::Cleanup %W } +ttk::bindMouseWheel TNotebook [list ttk::notebook::CycleTab %W] + # ActivateTab $nb $tab -- # Select the specified tab and set focus. # # Desired behavior: # + take focus when reselecting the currently-selected tab; @@ -54,16 +56,20 @@ } # CycleTab -- # Select the next/previous tab in the list. # -proc ttk::notebook::CycleTab {w dir} { - if {[$w index end] != 0} { - set current [$w index current] - set select [expr {($current + $dir) % [$w index end]}] - while {[$w tab $select -state] != "normal" && ($select != $current)} { - set select [expr {($select + $dir) % [$w index end]}] +proc ttk::notebook::CycleTab {w dir {factor 1.0}} { + set current [$w index current] + if {$current >= 0} { + set tabCount [$w index end] + set d [expr {$dir/$factor}] + set d [expr {int($d > 0 ? ceil($d) : floor($d))}] + set select [expr {($current + $d) % $tabCount}] + set step [expr {$d > 0 ? 1 : -1}] + while {[$w tab $select -state] ne "normal" && ($select != $current)} { + set select [expr {($select + $step) % $tabCount}] } if {$select != $current} { ActivateTab $w $select } } @@ -110,17 +116,12 @@ bind $top {+ttk::notebook::TLCycleTab %W 1} bind $top {+ttk::notebook::TLCycleTab %W -1} catch { bind $top {+ttk::notebook::TLCycleTab %W -1} } - if {[tk windowingsystem] eq "aqua"} { - bind $top \ - +[list ttk::notebook::MnemonicActivation $top %K] - } else { - bind $top \ - +[list ttk::notebook::MnemonicActivation $top %K] - } + bind $top \ + +[list ttk::notebook::MnemonicActivation $top %K] bind $top {+ttk::notebook::TLCleanup %W} } lappend TLNotebooks($top) $nb } Index: library/ttk/scale.tcl ================================================================== --- library/ttk/scale.tcl +++ library/ttk/scale.tcl @@ -1,6 +1,6 @@ -# scale.tcl - Copyright (C) 2004 Pat Thoyts +# scale.tcl - Copyright © 2004 Pat Thoyts # # Bindings for the TScale widget namespace eval ttk::scale { variable State Index: library/ttk/spinbox.tcl ================================================================== --- library/ttk/spinbox.tcl +++ library/ttk/spinbox.tcl @@ -21,11 +21,11 @@ bind TSpinbox { event generate %W <> } bind TSpinbox <> { ttk::spinbox::Spin %W +1 } bind TSpinbox <> { ttk::spinbox::Spin %W -1 } -ttk::bindMouseWheel TSpinbox [list ttk::spinbox::MouseWheel %W] +ttk::bindMouseWheel TSpinbox [list ttk::spinbox::Spin %W] ## Motion -- # Sets cursor. # proc ttk::spinbox::Motion {w x y} { @@ -78,17 +78,17 @@ ttk::CancelRepeat } ## MouseWheel -- # Mousewheel callback. Turn these into <> (-1, up) -# or < (+1, down) events. +# or < (+1, down) events. Not used any more. # -proc ttk::spinbox::MouseWheel {w dir {factor 1}} { +proc ttk::spinbox::MouseWheel {w dir {factor 1.0}} { if {[$w instate disabled]} { return } if {($dir < 0) ^ ($factor < 0)} { event generate $w <> - } elseif {$dir > 0} { + } elseif {$dir != 0} { event generate $w <> } } ## SelectAll -- @@ -132,11 +132,11 @@ # Handle <> and <> events. # If -values is specified, cycle through the list. # Otherwise cycle through numeric range based on # -from, -to, and -increment. # -proc ttk::spinbox::Spin {w dir} { +proc ttk::spinbox::Spin {w dir {factor -1.0}} { variable State if {[$w instate disabled]} { return } if {![info exists State($w,values.length)]} { @@ -144,24 +144,26 @@ set State($w,values.last) {} } set State($w,values) [$w cget -values] set State($w,values.length) [llength $State($w,values)] + set d [expr {-($dir/$factor)}] + set d [expr {int($d > 0 ? ceil($d) : floor($d))}] if {$State($w,values.length) > 0} { set value [$w get] set current $State($w,values.index) if {$value ne $State($w,values.last)} { set current [lsearch -exact $State($w,values) $value] if {$current < 0} {set current -1} } - set State($w,values.index) [Adjust $w [expr {$current + $dir}] 0 \ + set State($w,values.index) [Adjust $w [expr {$current + $d}] 0 \ [expr {$State($w,values.length) - 1}]] set State($w,values.last) [lindex $State($w,values) $State($w,values.index)] $w set $State($w,values.last) } else { if {[catch { - set v [expr {[scan [$w get] %f] + $dir * [$w cget -increment]}] + set v [expr {[scan [$w get] %f] + $d * [$w cget -increment]}] }]} { set v [$w cget -from] } $w set [FormatValue $w [Adjust $w $v [$w cget -from] [$w cget -to]]] } Index: library/ttk/utils.tcl ================================================================== --- library/ttk/utils.tcl +++ library/ttk/utils.tcl @@ -278,32 +278,27 @@ # Gtk+ and Qt do not appear to use as large a factor). # ## ttk::bindMouseWheel $bindtag $command... # Adds basic mousewheel support to $bindtag. -# $command will be passed one additional argument -# specifying the mousewheel direction (-1: up, +1: down). +# $command will be passed two additional arguments +# specifying the mousewheel change and a factor. # proc ttk::bindMouseWheel {bindtag callback} { - bind $bindtag [append callback { %D -120.0}] - bind $bindtag [append callback { %D -12.0}] + bind $bindtag "$callback %D -120.0" + bind $bindtag "$callback %D -12.0" } ## Mousewheel bindings for standard scrollable widgets. # -# Usage: [ttk::copyBindings TtkScrollable $bindtag] -# -# $bindtag should be for a widget that supports the -# standard scrollbar protocol. -# bind TtkScrollable \ - { tk::MouseWheel %W y %D } + { tk::MouseWheel %W y %D -40.0 } bind TtkScrollable \ { tk::MouseWheel %W y %D -12.0 } bind TtkScrollable \ - { tk::MouseWheel %W x %D } + { tk::MouseWheel %W x %D -40.0 } bind TtkScrollable \ { tk::MouseWheel %W x %D -12.0 } #*EOF* ADDED macosx/Credits.html.in Index: macosx/Credits.html.in ================================================================== --- /dev/null +++ macosx/Credits.html.in @@ -0,0 +1,24 @@ + + + + + +

+Tcl and Tk are distributed under a modified BSD license:
+ + https://www.tcl-lang.org/software/tcltk/license.html + +

+
    +
  • © 1987-@TK_YEAR@ Tcl Core Team and Contributers.
  • +
  • © 2011-@TK_YEAR@ Kevin Walzer/WordTech Communications LLC.
  • +
  • © 2014-@TK_YEAR@ Marc Culler.
  • +
  • © 2002-2012 Daniel A. Steffen.
  • +
  • © 2001-2009 Apple Inc.
  • +
  • © 2001-2002 Jim Ingham & Ian Reid.
  • +
  • © 1998-2000 Jim Ingham & Ray Johnson.
  • +
  • © 1998-2000 Scriptics Inc.
  • +
  • © 1996-1997 Sun Microsystems Inc.
  • +
+ + Index: macosx/GNUmakefile ================================================================== --- macosx/GNUmakefile +++ macosx/GNUmakefile @@ -44,16 +44,10 @@ # set to non-empty value to build TkX11 instead of TkAqua: TK_X11 ?= # Checks and overrides for subframework builds ifeq (${SUBFRAMEWORK}_${TK_X11},1_) -ifeq (${DYLIB_INSTALL_DIR},) - @echo "Cannot install subframework with empty DYLIB_INSTALL_DIR !" && false -endif -ifeq (${DESTDIR},) - @echo "Cannot install subframework with empty DESTDIR !" && false -endif override BUILD_DIR = ${DESTDIR}/build override INSTALL_PATH = /Frameworks endif #------------------------------------------------------------------------------------------------------- @@ -143,13 +137,13 @@ VERSION := ${VERSION}-X11 wish := ${wish}-X11 override EMBEDDED_BUILD := endif -INSTALL_TARGETS = install-binaries install-libraries +INSTALL_TARGETS = install-binaries install-libraries install-headers ifeq (${EMBEDDED_BUILD},) -INSTALL_TARGETS += install-private-headers install-headers install-demos +INSTALL_TARGETS += install-private-headers install-demos endif ifeq (${INSTALL_BUILD}_${EMBEDDED_BUILD}_${BUILD_STYLE},1__Deployment) INSTALL_TARGETS += html-tk ifneq (${INSTALL_MANPAGES},) INSTALL_TARGETS += install-doc @@ -191,11 +185,11 @@ ${objdir}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \ ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in mkdir -p "${OBJ_DIR}" && cd "${OBJ_DIR}" && \ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \ --prefix="${PREFIX}" --bindir="${BINDIR}" --libdir="${LIBDIR}" \ - --mandir="${MANDIR}" --enable-framework \ + --mandir="${MANDIR}" --enable-framework --disable-zipfs \ --with-tcl="${TCL_DIR}" \ ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS}; else ./config.status; fi ifneq (${VERSION},${TCL_VERSION}) @cd "${OBJ_DIR}" && sed -e 's#/Versions/${TCL_VERSION}#/Versions/${VERSION}#' \ tkConfig.sh > tkConfig.sh.1 && mv -f tkConfig.sh.1 tkConfig.sh Index: macosx/tkMacOSXBitmap.c ================================================================== --- macosx/tkMacOSXBitmap.c +++ macosx/tkMacOSXBitmap.c @@ -1,13 +1,13 @@ /* * tkMacOSXBitmap.c -- * * This file handles the implementation of native bitmaps. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -176,11 +176,11 @@ { NSString *iconUTI = OSTYPE_TO_UTI(PTR2UINT(source)); NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFileType: iconUTI]; CGSize size = CGSizeMake(builtInIconSize, builtInIconSize); - Pixmap pixmap = PixmapFromImage(display, iconImage, NSSizeToCGSize(size)); + Pixmap pixmap = PixmapFromImage(display, iconImage, size); return pixmap; } /* @@ -255,11 +255,11 @@ NSSize size = { .width = builtInIconSize, .height = builtInIconSize }; if (iconBitmapTable.buckets && (hPtr = Tcl_FindHashEntry(&iconBitmapTable, name))) { OSType type; - IconBitmap *iconBitmap = Tcl_GetHashValue(hPtr); + IconBitmap *iconBitmap = (IconBitmap *)Tcl_GetHashValue(hPtr); name = NULL; size = NSMakeSize(iconBitmap->width, iconBitmap->height); switch (iconBitmap->kind) { case ICON_FILE: string = [[NSString stringWithUTF8String:iconBitmap->value] @@ -401,11 +401,11 @@ if (!iconBitmapTable.buckets) { Tcl_InitHashTable(&iconBitmapTable, TCL_STRING_KEYS); } hPtr = Tcl_CreateHashEntry(&iconBitmapTable, name, &isNew); if (!isNew) { - iconBitmap = Tcl_GetHashValue(hPtr); + iconBitmap = (IconBitmap *)Tcl_GetHashValue(hPtr); ckfree(iconBitmap->value); } else { iconBitmap = (IconBitmap *)ckalloc(sizeof(IconBitmap)); Tcl_SetHashValue(hPtr, iconBitmap); } Index: macosx/tkMacOSXButton.c ================================================================== --- macosx/tkMacOSXButton.c +++ macosx/tkMacOSXButton.c @@ -2,16 +2,16 @@ * tkMacOSXButton.c -- * * This file implements the Macintosh specific portion of the button * widgets. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. - * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2006-2007 Daniel A. Steffen - * Copyright 2007 Revar Desmera. - * Copyright 2015 Kevin Walzer/WordTech Communications LLC. - * Copyright 2015 Marc Culler. + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 2001 Apple Computer, Inc. + * Copyright © 2006-2007 Daniel A. Steffen + * Copyright © 2007 Revar Desmera. + * Copyright © 2015 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2015 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ @@ -179,12 +179,12 @@ void TkpDisplayButton( ClientData clientData) /* Information about widget. */ { - MacButton *macButtonPtr = clientData; - TkButton *butPtr = clientData; + MacButton *macButtonPtr = (MacButton *)clientData; + TkButton *butPtr = (TkButton *)clientData; Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; DrawParams* dpPtr = &macButtonPtr->drawParams; int needhighlight = 0; @@ -899,12 +899,12 @@ static void ButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkButton *buttonPtr = clientData; - MacButton *mbPtr = clientData; + TkButton *buttonPtr = (TkButton *)clientData; + MacButton *mbPtr = (MacButton *)clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { return; @@ -955,11 +955,11 @@ *btnkind = kThemeRoundedBevelButton; } else { *btnkind = kThemePushButton; } - if ((butPtr->image == None) && (butPtr->bitmap == None)) { + if ((butPtr->image == NULL) && (butPtr->bitmap == None)) { switch (butPtr->type) { case TYPE_BUTTON: *btnkind = kThemePushButton; break; case TYPE_RADIO_BUTTON: @@ -1172,11 +1172,11 @@ */ static void PulseDefaultButtonProc(ClientData clientData) { - MacButton *mbPtr = clientData; + MacButton *mbPtr = (MacButton *)clientData; TkpDisplayButton(clientData); /* * Fix 40ada90762: any idle calls to TkpDisplayButton need to be canceled * in case the button is destroyed and has its data freed before the idle Index: macosx/tkMacOSXClipboard.c ================================================================== --- macosx/tkMacOSXClipboard.c +++ macosx/tkMacOSXClipboard.c @@ -1,13 +1,13 @@ /* * tkMacOSXClipboard.c -- * * This file manages the clipboard for the Tk toolkit. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -135,17 +135,11 @@ if (type) { string = [pb stringForType:type]; } if (string) { - if (target == dispPtr->utf8Atom) { - result = proc(clientData, interp, string.UTF8String); - } else if (target == XA_STRING) { - const char *latin1 = [string - cStringUsingEncoding:NSISOLatin1StringEncoding]; - result = proc(clientData, interp, latin1); - } + result = proc(clientData, interp, string.UTF8String); } } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s selection doesn't exist or form \"%s\" not defined", Tk_GetAtomName(tkwin, selection), Index: macosx/tkMacOSXColor.c ================================================================== --- macosx/tkMacOSXColor.c +++ macosx/tkMacOSXColor.c @@ -3,15 +3,15 @@ * * This file maintains a database of color values for the Tk * toolkit, in order to avoid round-trips to the server to * map color names to pixel values. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1996 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2020 Marc Culler + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1996 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2020 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -175,11 +175,11 @@ TkMacOSXRGBPixel( unsigned long red, unsigned long green, unsigned long blue) { - MacPixel p; + MacPixel p = {0}; p.pixel.colortype = rgbColor; p.pixel.value = ((red & 0xff) << 16) | ((green & 0xff) << 8) | (blue & 0xff); return p.ulong; @@ -205,11 +205,11 @@ */ MODULE_SCOPE unsigned long TkMacOSXClearPixel( void) { - MacPixel p; + MacPixel p = {0}; p.pixel.value = 0; p.pixel.colortype = clearColor; return p.ulong; } @@ -234,11 +234,11 @@ SystemColorDatum* GetEntryFromPixel( unsigned long pixel) { - MacPixel p; + MacPixel p = {0}; int index = rgbColorIndex; p.ulong = pixel; if (p.pixel.colortype != rgbColor) { index = p.pixel.value; @@ -280,10 +280,11 @@ NSColor *bgColor, *color = nil; if (!sRGB) { sRGB = [NSColorSpace sRGBColorSpace]; } + switch (entry->type) { case rgbColor: rgba[0] = ((pixel >> 16) & 0xff) / 255.0; rgba[1] = ((pixel >> 8) & 0xff) / 255.0; rgba[2] = ((pixel ) & 0xff) / 255.0; @@ -310,29 +311,33 @@ } else { for (int i=0; i<3; i++) { rgba[i] -= entry->value*8.0 / 255.0; } } + break; + case clearColor: + rgba[0] = rgba[1] = rgba[2] = 1.0; + rgba[3] = 0; break; case semantic: if (entry->index == controlAccentIndex && useFakeAccentColor) { #if MAC_OS_X_VERSION_MIN_REQUIRED < 101400 color = [[NSColor colorForControlTint: [NSColor currentControlTint]] colorUsingColorSpace:sRGB]; #endif } else if (entry->index == selectedTabTextIndex) { int OSVersion = [NSApp macOSVersion]; - if (OSVersion > 100600 && OSVersion < 110000) { + if (OSVersion > 100600 && OSVersion < 101600) { color = [[NSColor whiteColor] colorUsingColorSpace:sRGB]; + } else { + color = [[NSColor textColor] colorUsingColorSpace:sRGB]; } } else { color = [[NSColor valueForKey:entry->selector] colorUsingColorSpace:sRGB]; } [color getComponents: rgba]; break; - case clearColor: - rgba[3] = 0; default: break; } } @@ -414,10 +419,12 @@ } else { name = [[NSAppearance currentAppearance] name]; } return (name == NSAppearanceNameDarkAqua); } +#else + (void) tkwin; #endif return false; } /* @@ -426,26 +433,25 @@ * TkSetMacColor -- * * Sets the components of a CGColorRef from an XColor pixel value. The * pixel value is used to look up the color in the system color table, and * then SetCGColorComponents is called with the table entry and the pixel - * value. + * value. The parameter macColor should be a pointer to a CGColorRef. * * Results: * Returns false if the color is not found, true otherwise. * * Side effects: - * The variable macColor is set to a new CGColorRef, the caller is - * responsible for releasing it! + * The CGColorRef referenced by the variable macColor may be modified. * *---------------------------------------------------------------------- */ int TkSetMacColor( - unsigned long pixel, /* Pixel value to convert. */ - void *macColor) /* CGColorRef to modify. */ + unsigned long pixel, /* Pixel value to convert. */ + void *macColor) /* CGColorRef to modify. */ { CGColorRef *color = (CGColorRef*)macColor; SystemColorDatum *entry = GetEntryFromPixel(pixel); if (entry) { @@ -452,122 +458,10 @@ return SetCGColorComponents(entry, pixel, color); } else { return false; } } - -/* - *---------------------------------------------------------------------- - * - * TkpInitGCCache, TkpFreeGCCache, CopyCachedColor, SetCachedColor -- - * - * Maintain a per-GC cache of previously converted CGColorRefs - * - * Results: - * None resp. retained CGColorRef for CopyCachedColor() - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -void -TkpInitGCCache( - GC gc) -{ - bzero(TkpGetGCCache(gc), sizeof(TkpGCCache)); -} - -void -TkpFreeGCCache( - GC gc) -{ - TkpGCCache *gcCache = TkpGetGCCache(gc); - - if (gcCache->cachedForegroundColor) { - CFRelease(gcCache->cachedForegroundColor); - } - if (gcCache->cachedBackgroundColor) { - CFRelease(gcCache->cachedBackgroundColor); - } -} - -static CGColorRef -CopyCachedColor( - GC gc, - unsigned long pixel) -{ - TkpGCCache *gcCache = TkpGetGCCache(gc); - CGColorRef cgColor = NULL; - - if (gcCache) { - if (gcCache->cachedForeground == pixel) { - cgColor = gcCache->cachedForegroundColor; - } else if (gcCache->cachedBackground == pixel) { - cgColor = gcCache->cachedBackgroundColor; - } - if (cgColor) { - CFRetain(cgColor); - } - } - return cgColor; -} - -static void -SetCachedColor( - GC gc, - unsigned long pixel, - CGColorRef cgColor) -{ - TkpGCCache *gcCache = TkpGetGCCache(gc); - - if (gcCache && cgColor) { - if (gc->foreground == pixel) { - if (gcCache->cachedForegroundColor) { - CFRelease(gcCache->cachedForegroundColor); - } - gcCache->cachedForegroundColor = (CGColorRef) CFRetain(cgColor); - gcCache->cachedForeground = pixel; - } else if (gc->background == pixel) { - if (gcCache->cachedBackgroundColor) { - CFRelease(gcCache->cachedBackgroundColor); - } - gcCache->cachedBackgroundColor = (CGColorRef) CFRetain(cgColor); - gcCache->cachedBackground = pixel; - } - } -} - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXCreateCGColor -- - * - * Creates a CGColorRef from a X style pixel value. - * - * Results: - * Returns NULL if not a real pixel, CGColorRef otherwise. - * - * Side effects: - * None - * - *---------------------------------------------------------------------- - */ - -CGColorRef -TkMacOSXCreateCGColor( - GC gc, - unsigned long pixel) /* Pixel value to convert. */ -{ - CGColorRef cgColor = CopyCachedColor(gc, pixel); - - if (!cgColor && TkSetMacColor(pixel, &cgColor)) { - SetCachedColor(gc, pixel, cgColor); - } - return cgColor; -} /* *---------------------------------------------------------------------- * * TkMacOSXGetNSColor -- @@ -584,26 +478,20 @@ *---------------------------------------------------------------------- */ NSColor* TkMacOSXGetNSColor( - GC gc, + TCL_UNUSED(GC), unsigned long pixel) /* Pixel value to convert. */ { - CGColorRef cgColor = TkMacOSXCreateCGColor(gc, pixel); + CGColorRef cgColor; NSColor *nsColor = nil; - if (cgColor) { - NSColorSpace *colorSpace = [[NSColorSpace alloc] - initWithCGColorSpace:CGColorGetColorSpace(cgColor)]; - - nsColor = [NSColor colorWithColorSpace:colorSpace - components:CGColorGetComponents(cgColor) - count:CGColorGetNumberOfComponents(cgColor)]; - [colorSpace release]; - CFRelease(cgColor); - } + TkSetMacColor(pixel, &cgColor); + nsColor = [NSColor colorWithColorSpace:sRGB + components:CGColorGetComponents(cgColor) + count:CGColorGetNumberOfComponents(cgColor)]; return nsColor; } /* *---------------------------------------------------------------------- @@ -623,11 +511,11 @@ *---------------------------------------------------------------------- */ void TkMacOSXSetColorInContext( - GC gc, + TCL_UNUSED(GC), unsigned long pixel, CGContextRef context) { OSStatus err = noErr; CGColorRef cgColor = nil; @@ -642,13 +530,11 @@ err = ChkErr(HIThemeSetStroke, entry->value, NULL, context, kHIThemeOrientationNormal); } break; default: - if (SetCGColorComponents(entry, pixel, &cgColor)){ - SetCachedColor(gc, pixel, cgColor); - } + SetCGColorComponents(entry, pixel, &cgColor); break; } } if (cgColor) { CGContextSetFillColorWithColor(context, cgColor); @@ -693,11 +579,11 @@ TkColor *tkColPtr; XColor color; Colormap colormap = tkwin ? Tk_Colormap(tkwin) : noColormap; NSView *view = nil; static Bool initialized = NO; - static NSColorSpace* sRGB = NULL; + static NSColorSpace* sRGB = nil; if (!initialized) { initialized = YES; sRGB = [NSColorSpace sRGBColorSpace]; initColorTable(); @@ -712,11 +598,11 @@ * Check to see if this is a system color. If not, just call XParseColor. */ if (strncasecmp(name, "system", 6) == 0) { Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&systemColors, name + 6); - MacPixel p; + MacPixel p = {0}; if (hPtr != NULL) { SystemColorDatum *entry = (SystemColorDatum *)Tcl_GetHashValue(hPtr); CGColorRef c; Index: macosx/tkMacOSXColor.h ================================================================== --- macosx/tkMacOSXColor.h +++ macosx/tkMacOSXColor.h @@ -85,11 +85,11 @@ * constructed. Failing to ensure this will result in a Tcl_Panic abort. */ static SystemColorDatum systemColorData[] = { {"Pixel", rgbColor, 0, NULL, 0, NULL }, -{"Transparent", clearColor, 0, NULL, 0, NULL }, +{"Transparent", clearColor, 0, NULL, 0, NULL }, {"Highlight", HIBrush, kThemeBrushPrimaryHighlightColor, NULL, 0, NULL }, {"HighlightSecondary", HIBrush, kThemeBrushSecondaryHighlightColor, NULL, 0, NULL }, {"HighlightText", HIBrush, kThemeBrushBlack, NULL, 0, NULL }, {"HighlightAlternate", HIBrush, kThemeBrushAlternatePrimaryHighlightColor, NULL, 0, NULL }, @@ -182,11 +182,12 @@ {"ControlAccentColor", semantic, 0, "controlAccentColor", 0, NULL }, {"LabelColor", semantic, 0, "blackColor", 0, NULL }, {"LinkColor", semantic, 0, "blueColor", 0, NULL }, {"PlaceholderTextColor", semantic, 0, "grayColor", 0, NULL }, {"SeparatorColor", semantic, 0, "grayColor", 0, NULL }, -{NULL, 0, 0, NULL, 0, NULL } +{"UnemphasizedSelectedTextBackgroundColor", semantic, 0, "grayColor", 0, NULL }, +{NULL, rgbColor, 0, NULL, 0, NULL } }; #endif /* * Local Variables: Index: macosx/tkMacOSXConfig.c ================================================================== --- macosx/tkMacOSXConfig.c +++ macosx/tkMacOSXConfig.c @@ -2,12 +2,12 @@ * tkMacOSXConfig.c -- * * This module implements the Macintosh system defaults for * the configuration package. * - * Copyright (c) 1997 by Sun Microsystems, Inc. - * Copyright 2001, Apple Inc. + * Copyright © 1997 Sun Microsystems, Inc. + * Copyright © 2001, Apple Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXConstants.h ================================================================== --- macosx/tkMacOSXConstants.h +++ macosx/tkMacOSXConstants.h @@ -4,11 +4,11 @@ * Macros which map the names of NS constants used in the Tk code to * the new name that Apple came up with for subsequent versions of the * operating system. (Each new OS release seems to come with a new * naming convention for the same old constants.) * - * Copyright (c) 2017 Marc Culler + * Copyright © 2017 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXCursor.c ================================================================== --- macosx/tkMacOSXCursor.c +++ macosx/tkMacOSXCursor.c @@ -1,13 +1,13 @@ /* * tkMacOSXCursor.c -- * * This file contains Macintosh specific cursor related routines. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -260,11 +260,11 @@ case IMAGEPATH: path = [NSApp tkFrameworkImagePath:cursorNames[idx].id1]; break; case IMAGEBITMAP: { unsigned char *bitmap = (unsigned char *)(cursorNames[idx].id1); - NSBitmapImageRep *bitmapImageRep = NULL; + NSBitmapImageRep *bitmapImageRep = nil; CGImageRef img = NULL, mask = NULL, maskedImg = NULL; static const CGFloat decodeWB[] = {1, 0}; CGColorSpaceRef colorspace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, @@ -455,11 +455,11 @@ TkCursor *cursorPtr) { TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr; [macCursorPtr->macCursor release]; - macCursorPtr->macCursor = NULL; + macCursorPtr->macCursor = nil; if (macCursorPtr == gCurrentCursor) { gCurrentCursor = NULL; } } @@ -534,11 +534,11 @@ TkpSetCursor( TkpCursor cursor) { int cursorChanged = 1; - if (cursor == None) { + if (cursor == NULL) { /* * This is a little tricky. We can't really tell whether * gCurrentCursor is NULL because it was NULL last time around or * because we just freed the current cursor. So if the input cursor is * NULL, we always need to reset it, we can't trust the cursorChanged Index: macosx/tkMacOSXCursors.h ================================================================== --- macosx/tkMacOSXCursors.h +++ macosx/tkMacOSXCursors.h @@ -2,13 +2,13 @@ * tkMacOSXCursors.h -- * * This file defines a set of Macintosh cursor resources that * are only available on the Macintosh platform. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. - * Copyright 2008-2009, Apple Inc. - * Copyright (c) 2008-2009 Daniel A. Steffen + * Copyright © 1995-1996 Sun Microsystems, Inc. + * Copyright © 2008-2009 Apple Inc. + * Copyright © 2008-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXDebug.c ================================================================== --- macosx/tkMacOSXDebug.c +++ macosx/tkMacOSXDebug.c @@ -2,12 +2,12 @@ * tkMacOSXDebug.c -- * * Implementation of Macintosh specific functions for debugging MacOS * events, regions, etc... * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXDebug.h ================================================================== --- macosx/tkMacOSXDebug.h +++ macosx/tkMacOSXDebug.h @@ -2,12 +2,12 @@ * tkMacOSXDebug.h -- * * Declarations of Macintosh specific functions for debugging MacOS events, * regions, etc... * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXDefault.h ================================================================== --- macosx/tkMacOSXDefault.h +++ macosx/tkMacOSXDefault.h @@ -40,14 +40,15 @@ #define NORMAL_FG "systemTextColor" #define ACTIVE_BG "systemWindowBackgroundColor" #define ACTIVE_FG "systemTextColor" #define SELECT_BG "systemSelectedTextBackgroundColor" #define SELECT_FG "systemSelectedTextColor" -#define INACTIVE_SELECT_BG "systemSelectedTextBackgroundColor" +#define INACTIVE_SELECT_BG "systemUnemphasizedSelectedTextBackgroundColor" #define TROUGH "#c3c3c3" #define INDICATOR "#b03060" #define DISABLED "systemDisabledControlTextColor" +#define IGNORED "#abcdef" /* * Defaults for labels, buttons, checkbuttons, and radiobuttons: */ @@ -71,11 +72,11 @@ #define DEF_CHKRAD_FG DEF_BUTTON_FG #define DEF_BUTTON_FONT "TkDefaultFont" #define DEF_BUTTON_HEIGHT "0" #define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR #define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO -#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame" +#define DEF_BUTTON_HIGHLIGHT NORMAL_FG #define DEF_LABEL_HIGHLIGHT_WIDTH "0" //#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS //#define DEF_BUTTON_HIGHLIGHT_WIDTH "4" //#define DEF_BUTTON_HIGHLIGHT_WIDTH_NOCM "1" //#else @@ -86,23 +87,13 @@ #define DEF_BUTTON_JUSTIFY "center" #define DEF_BUTTON_OFF_VALUE "0" #define DEF_BUTTON_ON_VALUE "1" #define DEF_BUTTON_TRISTATE_VALUE "" #define DEF_BUTTON_OVER_RELIEF "" -//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS -//#define DEF_BUTTON_PADX "12" -//#define DEF_BUTTON_PADX_NOCM "1" -//#else #define DEF_BUTTON_PADX "1" -//#endif #define DEF_LABCHKRAD_PADX "1" -//#if TK_MAC_BUTTON_USE_COMPATIBILITY_METRICS -//#define DEF_BUTTON_PADY "3" -//#define DEF_BUTTON_PADY_NOCM "1" -//#else #define DEF_BUTTON_PADY "1" -//#endif #define DEF_LABCHKRAD_PADY "1" #define DEF_BUTTON_RELIEF "flat" #define DEF_LABCHKRAD_RELIEF "flat" #define DEF_BUTTON_REPEAT_DELAY "0" #define DEF_BUTTON_REPEAT_INTERVAL "0" @@ -112,11 +103,10 @@ #define DEF_BUTTON_STATE "normal" #define DEF_LABEL_TAKE_FOCUS "0" #define DEF_BUTTON_TAKE_FOCUS NULL #define DEF_BUTTON_TEXT "" #define DEF_BUTTON_TEXT_VARIABLE "" -#define DEF_BUTTON_UNDERLINE "-1" #define DEF_BUTTON_VALUE "" #define DEF_BUTTON_WIDTH "0" #define DEF_BUTTON_WRAP_LENGTH "0" #define DEF_RADIOBUTTON_VARIABLE "selectedButton" #define DEF_CHECKBUTTON_VARIABLE "" @@ -131,11 +121,11 @@ #define DEF_CANVAS_CLOSE_ENOUGH "1" #define DEF_CANVAS_CONFINE "1" #define DEF_CANVAS_CURSOR "" #define DEF_CANVAS_HEIGHT "7c" #define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG -#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT NORMAL_FG #define DEF_CANVAS_HIGHLIGHT_WIDTH "3" #define DEF_CANVAS_INSERT_BG BLACK #define DEF_CANVAS_INSERT_BD_COLOR "0" #define DEF_CANVAS_INSERT_BD_MONO "0" #define DEF_CANVAS_INSERT_OFF_TIME "300" @@ -181,11 +171,11 @@ #define DEF_ENTRY_DISABLED_FG DISABLED #define DEF_ENTRY_EXPORT_SELECTION "1" #define DEF_ENTRY_FONT "TkTextFont" #define DEF_ENTRY_FG NORMAL_FG #define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG -#define DEF_ENTRY_HIGHLIGHT BLACK +#define DEF_ENTRY_HIGHLIGHT NORMAL_FG #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" #define DEF_ENTRY_INSERT_BG NORMAL_FG #define DEF_ENTRY_INSERT_BD_COLOR "0" #define DEF_ENTRY_INSERT_BD_MONO "0" #define DEF_ENTRY_INSERT_OFF_TIME "300" @@ -223,11 +213,11 @@ #define DEF_FRAME_COLORMAP "" #define DEF_FRAME_CONTAINER "0" #define DEF_FRAME_CURSOR "" #define DEF_FRAME_HEIGHT "0" #define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG -#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT NORMAL_FG #define DEF_FRAME_HIGHLIGHT_WIDTH "0" #define DEF_FRAME_PADX "0" #define DEF_FRAME_PADY "0" #define DEF_FRAME_RELIEF "flat" #define DEF_FRAME_TAKE_FOCUS "0" @@ -259,11 +249,11 @@ #define DEF_LISTBOX_EXPORT_SELECTION "1" #define DEF_LISTBOX_FONT "TkTextFont" #define DEF_LISTBOX_FG NORMAL_FG #define DEF_LISTBOX_HEIGHT "10" #define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG -#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT NORMAL_FG #define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" #define DEF_LISTBOX_JUSTIFY "left" #define DEF_LISTBOX_RELIEF "solid" #define DEF_LISTBOX_SCROLL_COMMAND "" #define DEF_LISTBOX_LIST_VARIABLE "" @@ -303,34 +293,33 @@ #define DEF_MENU_ENTRY_STATE "normal" #define DEF_MENU_ENTRY_VALUE NULL #define DEF_MENU_ENTRY_CHECK_VARIABLE NULL #define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" #define DEF_MENU_ENTRY_SELECT NULL -#define DEF_MENU_ENTRY_UNDERLINE "-1" /* * Defaults for menus overall: */ -#define DEF_MENU_ACTIVE_BG_COLOR NORMAL_BG /*ignored*/ -#define DEF_MENU_ACTIVE_BG_MONO NORMAL_BG /*ignored*/ +#define DEF_MENU_ACTIVE_BG_COLOR IGNORED +#define DEF_MENU_ACTIVE_BG_MONO IGNORED #define DEF_MENU_ACTIVE_BORDER_WIDTH "0" -#define DEF_MENU_ACTIVE_FG_COLOR NORMAL_FG -#define DEF_MENU_ACTIVE_FG_MONO NORMAL_FG +#define DEF_MENU_ACTIVE_FG_COLOR IGNORED +#define DEF_MENU_ACTIVE_FG_MONO IGNORED #define DEF_MENU_ACTIVE_RELIEF "flat" -#define DEF_MENU_BG_COLOR NORMAL_BG /*ignored*/ -#define DEF_MENU_BG_MONO NORMAL_BG /*ignored*/ +#define DEF_MENU_BG_COLOR "#000001" /* Detects custom bg. */ +#define DEF_MENU_BG_MONO IGNORED #define DEF_MENU_BORDER_WIDTH "0" #define DEF_MENU_CURSOR "arrow" -#define DEF_MENU_DISABLED_FG_COLOR DISABLED -#define DEF_MENU_DISABLED_FG_MONO DISABLED +#define DEF_MENU_DISABLED_FG_COLOR IGNORED +#define DEF_MENU_DISABLED_FG_MONO "" #define DEF_MENU_FONT "menu" /* special: see tkMacOSXMenu.c */ -#define DEF_MENU_FG NORMAL_FG +#define DEF_MENU_FG "#010000" /* Detects custom fg. */ #define DEF_MENU_POST_COMMAND "" #define DEF_MENU_RELIEF "flat" -#define DEF_MENU_SELECT_COLOR "systemSelectedMenuItemTextColor" -#define DEF_MENU_SELECT_MONO "systemSelectedMenuItemTextColor" +#define DEF_MENU_SELECT_COLOR IGNORED +#define DEF_MENU_SELECT_MONO IGNORED #define DEF_MENU_TAKE_FOCUS "0" #define DEF_MENU_TEAROFF "0" #define DEF_MENU_TEAROFF_CMD NULL #define DEF_MENU_TITLE "" #define DEF_MENU_TYPE "normal" @@ -355,11 +344,11 @@ #define DEF_MENUBUTTON_FONT "TkDefaultFont" #define DEF_MENUBUTTON_FG NORMAL_FG #define DEF_MENUBUTTON_HEIGHT "0" #define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR #define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO -#define DEF_MENUBUTTON_HIGHLIGHT NORMAL_BG +#define DEF_MENUBUTTON_HIGHLIGHT NORMAL_FG #define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" #define DEF_MENUBUTTON_IMAGE NULL #define DEF_MENUBUTTON_INDICATOR "1" #define DEF_MENUBUTTON_JUSTIFY "left" #define DEF_MENUBUTTON_MENU "" @@ -368,11 +357,10 @@ #define DEF_MENUBUTTON_RELIEF "flat" #define DEF_MENUBUTTON_STATE "normal" #define DEF_MENUBUTTON_TAKE_FOCUS "0" #define DEF_MENUBUTTON_TEXT "" #define DEF_MENUBUTTON_TEXT_VARIABLE "" -#define DEF_MENUBUTTON_UNDERLINE "-1" #define DEF_MENUBUTTON_WIDTH "0" #define DEF_MENUBUTTON_WRAP_LENGTH "0" /* * Defaults for messages: @@ -385,11 +373,11 @@ #define DEF_MESSAGE_BORDER_WIDTH "1" #define DEF_MESSAGE_CURSOR "" #define DEF_MESSAGE_FG NORMAL_FG #define DEF_MESSAGE_FONT "TkDefaultFont" #define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG -#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT NORMAL_FG #define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" #define DEF_MESSAGE_JUSTIFY "left" #define DEF_MESSAGE_PADX "-1" #define DEF_MESSAGE_PADY "-1" #define DEF_MESSAGE_RELIEF "flat" @@ -451,11 +439,11 @@ #define DEF_SCALE_FG_COLOR NORMAL_FG #define DEF_SCALE_FG_MONO BLACK #define DEF_SCALE_FROM "0" #define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR #define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO -#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT NORMAL_FG #define DEF_SCALE_HIGHLIGHT_WIDTH "0" #define DEF_SCALE_LABEL "" #define DEF_SCALE_LENGTH "100" #define DEF_SCALE_ORIENT "vertical" #define DEF_SCALE_RELIEF "flat" @@ -486,11 +474,11 @@ #define DEF_SCROLLBAR_BORDER_WIDTH "0" #define DEF_SCROLLBAR_COMMAND "" #define DEF_SCROLLBAR_CURSOR "" #define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" #define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG -#define DEF_SCROLLBAR_HIGHLIGHT BLACK +#define DEF_SCROLLBAR_HIGHLIGHT NORMAL_FG #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" #define DEF_SCROLLBAR_JUMP "0" #define DEF_SCROLLBAR_ORIENT "vertical" #define DEF_SCROLLBAR_RELIEF "flat" #define DEF_SCROLLBAR_REPEAT_DELAY "300" @@ -513,11 +501,11 @@ #define DEF_TEXT_FG NORMAL_FG #define DEF_TEXT_EXPORT_SELECTION "1" #define DEF_TEXT_FONT "TkFixedFont" #define DEF_TEXT_HEIGHT "24" #define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG -#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT NORMAL_FG #define DEF_TEXT_HIGHLIGHT_WIDTH "3" #define DEF_TEXT_INSERT_BG NORMAL_FG #define DEF_TEXT_INSERT_BD_COLOR "0" #define DEF_TEXT_INSERT_BD_MONO "0" #define DEF_TEXT_INSERT_OFF_TIME "300" Index: macosx/tkMacOSXDialog.c ================================================================== --- macosx/tkMacOSXDialog.c +++ macosx/tkMacOSXDialog.c @@ -1,14 +1,14 @@ /* * tkMacOSXDialog.c -- * * Contains the Mac implementation of the common dialog boxes. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2017 Christian Gollwitzer. + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2017 Christian Gollwitzer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -21,11 +21,11 @@ #define modalCancel NSCancelButton #else #define modalOK NSModalResponseOK #define modalCancel NSModalResponseCancel #endif // MAC_OS_X_VERSION_MIN_REQUIRED < 1090 -#define modalOther -1 // indicates that the -command option was used. +#define modalOther -1 // indicates that the -command option was used. #define modalError -2 /* * Vars for filtering in "open file" and "save file" dialogs. */ @@ -219,11 +219,11 @@ - (void) tkFilePanelDidEnd: (NSSavePanel *) panel returnCode: (NSModalResponse) returnCode contextInfo: (void *) contextInfo { - FilePanelCallbackInfo *callbackInfo = contextInfo; + FilePanelCallbackInfo *callbackInfo = (FilePanelCallbackInfo *)contextInfo; if (returnCode == modalOK) { Tcl_Obj *resultObj; if (callbackInfo->multiple) { @@ -264,11 +264,11 @@ } - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { - AlertCallbackInfo *callbackInfo = contextInfo; + AlertCallbackInfo *callbackInfo = (AlertCallbackInfo *)contextInfo; if (returnCode >= NSAlertFirstButtonReturn) { Tcl_Obj *resultObj = Tcl_NewStringObj(alertButtonStrings[ alertNativeButtonIndexAndTypeToButtonIndex[callbackInfo-> typeIndex][returnCode - NSAlertFirstButtonReturn]], -1); @@ -300,11 +300,10 @@ } - (void)selectFormat:(id)sender { NSPopUpButton *button = (NSPopUpButton *)sender; filterInfo.fileTypeIndex = [button indexOfSelectedItem]; - if ([[filterInfo.fileTypeAllowsAll objectAtIndex:filterInfo.fileTypeIndex] boolValue]) { [openpanel setAllowsOtherFileTypes:YES]; /* * setAllowsOtherFileTypes might have no effect; it's inherited from @@ -351,10 +350,11 @@ FilePanelCallbackInfo *callbackInfo) { NSInteger modalReturnCode; if (parent && ![parent attachedSheet]) { + int osVersion = [NSApp macOSVersion]; [panel beginSheetModalForWindow:parent completionHandler:^(NSModalResponse returnCode) { [NSApp tkFilePanelDidEnd:panel returnCode:returnCode contextInfo:callbackInfo ]; @@ -363,21 +363,26 @@ /* * The sheet has been prepared, so now we have to run it as a modal * window. Using [NSApp runModalForWindow:] on macOS 10.15 or later * generates warnings on stderr. But using [NSOpenPanel runModal] or * [NSSavePanel runModal] on 10.14 or earler does not cause the - * completion handler to run when the panel is closed. + * completion handler to run when the panel is closed. Apple apparently + * decided to go back to using runModalForWindow with the release of + * macOS 12.0. The warnings do not appear in that OS, and using + * runModal produces an error dialog that says "The open file operation + * failed to connect to the open and save panel service." along with an + * assertion error. */ - if ([NSApp macOSVersion] > 101400) { + if ( osVersion > 101400 && osVersion < 120000) { modalReturnCode = [panel runModal]; } else { modalReturnCode = [NSApp runModalForWindow:panel]; } } else { - /* + /* * For the standalone file dialog, completion handlers do not work * at all on macOS 10.14 and earlier. */ if ([NSApp macOSVersion] > 101400) { @@ -421,11 +426,11 @@ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { int result = TCL_ERROR; - Tk_Window parent, tkwin = clientData; + Tk_Window parent, tkwin = (Tk_Window)clientData; const char *title = NULL; int i; NSColor *color = nil, *initialColor = nil; NSColorPanel *colorPanel; NSInteger returnCode, numberOfComponents = 0; @@ -676,11 +681,11 @@ ClientData clientData, /* Main window associated with interpreter. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tk_Window tkwin = clientData; + Tk_Window tkwin = (Tk_Window)clientData; char *str; int i, result = TCL_ERROR, haveParentOption = 0; int index, len, multiple = 0; Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL; FilePanelCallbackInfo callbackInfoStruct; @@ -797,10 +802,11 @@ [label setStringValue:@"Filter:"]; [label setBordered:NO]; [label setBezeled:NO]; [label setDrawsBackground:NO]; [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; + [popupButton setTarget:NSApp]; [popupButton setAction:@selector(selectFormat:)]; [accessoryView addSubview:label]; [accessoryView addSubview:popupButton]; if (filterInfo.preselectFilter) { @@ -1082,12 +1088,12 @@ NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 340, 22.0) pullsDown:NO]; [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; + [popupButton setTarget:NSApp]; [popupButton setAction:@selector(saveFormat:)]; - [accessoryView addSubview:label]; [accessoryView addSubview:popupButton]; [savepanel setAccessoryView:accessoryView]; @@ -1313,68 +1319,13 @@ */ void TkAboutDlg(void) { - NSImage *image; - NSString *path = [NSApp tkFrameworkImagePath: @"Tk.tiff"]; - - if (path) { - image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease]; - } else { - image = [NSApp applicationIconImage]; - } - - NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; - - [dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4]; - [dateFormatter setDateFormat:@"Y"]; - - NSString *year = [dateFormatter stringFromDate:[NSDate date]]; - - [dateFormatter release]; - - /* - * This replaces the old about dialog with a standard alert that displays - * correctly on 10.14. - */ - - NSString *version = @"Tcl " TCL_PATCH_LEVEL " & Tk " TCL_PATCH_LEVEL; - NSString *url = @"www.tcl-lang.org"; - NSTextView *credits = [[NSTextView alloc] initWithFrame:NSMakeRect(0,0,300,300)]; - NSFont *font = [NSFont systemFontOfSize:[NSFont systemFontSize]]; - NSDictionary *textAttributes = [NSDictionary dictionaryWithObject:font - forKey:NSFontAttributeName]; - - [credits insertText: [[NSAttributedString alloc] - initWithString:[NSString stringWithFormat: @"\n" - "Tcl and Tk are distributed under a modified BSD license: " - "www.tcl.tk/software/tcltk/license.html\n\n" - "%1$C 1987-%2$@ Tcl Core Team and Contributers.\n\n" - "%1$C 2011-%2$@ Kevin Walzer/WordTech Communications LLC.\n\n" - "%1$C 2014-%2$@ Marc Culler.\n\n" - "%1$C 2002-2012 Daniel A. Steffen.\n\n" - "%1$C 2001-2009 Apple Inc.\n\n" - "%1$C 2001-2002 Jim Ingham & Ian Reid\n\n" - "%1$C 1998-2000 Jim Ingham & Ray Johnson\n\n" - "%1$C 1998-2000 Scriptics Inc.\n\n" - "%1$C 1996-1997 Sun Microsystems Inc.", 0xA9, year] - attributes:textAttributes] - replacementRange:NSMakeRange(0,0)]; - [credits setDrawsBackground:NO]; - [credits setEditable:NO]; - - NSAlert *about = [[NSAlert alloc] init]; - - [[about window] setTitle:@"About Tcl & Tk"]; - [about setMessageText: version]; - [about setInformativeText:url]; - about.accessoryView = credits; - [about runModal]; - [about release]; -} - + [NSApp orderFrontStandardAboutPanel:nil]; +} + /* *---------------------------------------------------------------------- * * TkMacOSXStandardAboutPanelObjCmd -- * @@ -1398,11 +1349,11 @@ { if (objc > 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } - TkAboutDlg(); + [NSApp orderFrontStandardAboutPanel:nil]; return TCL_OK; } /* *---------------------------------------------------------------------- @@ -1732,14 +1683,14 @@ Tcl_Obj *fontObj; if (!fontchooserInterp) { return; } - fcdPtr = Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); + fcdPtr = (FontchooserData *)Tcl_GetAssocData(fontchooserInterp, "::tk::fontchooser", NULL); switch (kind) { case FontchooserClosed: - if (fcdPtr->parent != None) { + if (fcdPtr->parent != NULL) { Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserVisibility", NULL); fontchooserInterp = NULL; } break; case FontchooserSelection: @@ -1791,11 +1742,11 @@ { Tcl_Obj *resObj = NULL; switch(optionIndex) { case FontchooserParent: - if (fcdPtr->parent != None) { + if (fcdPtr->parent != NULL) { resObj = Tcl_NewStringObj( ((TkWindow *)fcdPtr->parent)->pathName, -1); } else { resObj = Tcl_NewStringObj(".", 1); } @@ -1854,11 +1805,11 @@ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tk_Window tkwin = (Tk_Window)clientData; - FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", + FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", NULL); int i, r = TCL_OK; /* * With no arguments we return all the options in a dict @@ -1911,11 +1862,11 @@ } case FontchooserParent: { Tk_Window parent = Tk_NameToWindow(interp, Tcl_GetString(objv[i+1]), tkwin); - if (parent == None) { + if (parent == NULL) { return TCL_ERROR; } if (fcdPtr->parent) { Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); @@ -1938,11 +1889,11 @@ Tcl_IncrRefCount(fcdPtr->titleObj); } else { fcdPtr->titleObj = NULL; } break; - case FontchooserFont: + case FontchooserFont: { Tcl_GetStringFromObj(objv[i+1], &len); if (len) { Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, objv[i+1]); if (!f) { @@ -1972,10 +1923,11 @@ if ([fp isVisible]) { Tk_SendVirtualEvent(fcdPtr->parent, "TkFontchooserFontChanged", NULL); } break; + } case FontchooserCmd: if (fcdPtr->cmdObj) { Tcl_DecrRefCount(fcdPtr->cmdObj); } Tcl_GetStringFromObj(objv[i+1], &len); @@ -2017,14 +1969,14 @@ ClientData clientData, /* Main window */ Tcl_Interp *interp, TCL_UNUSED(int), TCL_UNUSED(Tcl_Obj *const *)) { - FontchooserData *fcdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", + FontchooserData *fcdPtr = (FontchooserData *)Tcl_GetAssocData(interp, "::tk::fontchooser", NULL); - if (fcdPtr->parent == None) { + if (fcdPtr->parent == NULL) { fcdPtr->parent = (Tk_Window)clientData; Tk_CreateEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); } @@ -2095,11 +2047,11 @@ static void FontchooserParentEventHandler( ClientData clientData, XEvent *eventPtr) { - FontchooserData *fcdPtr = clientData; + FontchooserData *fcdPtr = (FontchooserData *)clientData; if (eventPtr->type == DestroyNotify) { Tk_DeleteEventHandler(fcdPtr->parent, StructureNotifyMask, FontchooserParentEventHandler, fcdPtr); fcdPtr->parent = NULL; @@ -2127,11 +2079,11 @@ static void DeleteFontchooserData( ClientData clientData, Tcl_Interp *interp) { - FontchooserData *fcdPtr = clientData; + FontchooserData *fcdPtr = (FontchooserData *)clientData; if (fcdPtr->titleObj) { Tcl_DecrRefCount(fcdPtr->titleObj); } if (fcdPtr->cmdObj) { Index: macosx/tkMacOSXDraw.c ================================================================== --- macosx/tkMacOSXDraw.c +++ macosx/tkMacOSXDraw.c @@ -2,14 +2,14 @@ * tkMacOSXDraw.c -- * * This file contains functions that draw to windows. Many of thees * functions emulate Xlib functions. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 2001-2009 Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2014-2020 Marc Culler. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2014-2020 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -25,10 +25,11 @@ /* #ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_DRAWING #define TK_MAC_DEBUG_IMAGE_DRAWING +#define TK_MAC_DEBUG_CG #endif */ #define radians(d) ((d) * (M_PI/180.0)) @@ -511,11 +512,11 @@ /* *---------------------------------------------------------------------- * * XFillPolygon -- * - * Draws a filled polygon. + * Draws a filled polygon using the even-odd fill algorithm, * * Results: * None. * * Side effects: @@ -529,11 +530,11 @@ Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ XPoint *points, /* Array of points. */ int npoints, /* Number of points. */ - TCL_UNUSED(int), /* Shape to draw. */ + TCL_UNUSED(int), /* Shape to draw. */ int mode) /* Drawing mode. */ { MacDrawable *macWin = (MacDrawable *)d; TkMacOSXDrawingContext dc; int i; @@ -1240,10 +1241,16 @@ { MacDrawable *macDraw = (MacDrawable *)d; Bool canDraw = true; TKContentView *view = nil; TkMacOSXDrawingContext dc = {}; + CGFloat drawingHeight; + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif /* * If the drawable is not a pixmap, get the associated NSView. */ @@ -1271,18 +1278,14 @@ * If the drawable already has a CGContext, use it. Otherwise, we must be * drawing to a window and we use the current context of its ContentView. */ dc.context = TkMacOSXGetCGContextForDrawable(d); - if (dc.context) { - dc.portBounds = CGContextGetClipBoundingBox(dc.context); - } else { + if (!dc.context) { NSRect drawingBounds, currentBounds; - dc.view = view; dc.context = GET_CGCONTEXT; - dc.portBounds = NSRectToCGRect([view bounds]); if (dc.clipRgn) { CGRect clipBounds; CGAffineTransform t = { .a = 1, .b = 0, .c = 0, .d = -1, .tx = 0, .ty = [view bounds].size.height}; HIShapeGetBounds(dc.clipRgn, &clipBounds); @@ -1320,32 +1323,38 @@ * the drawing bounds will be clipped then we draw whatever we can, but * we also add the drawing bounds to the view's dirty rectangle so it * will get redrawn in the next call to its drawRect method. */ - currentBounds = CGContextGetClipBoundingBox(dc.context); + currentBounds = NSRectFromCGRect(CGContextGetClipBoundingBox(dc.context)); if (!NSContainsRect(currentBounds, drawingBounds)) { [view addTkDirtyRect:drawingBounds]; } } /* * Finish configuring the drawing context. */ - CGAffineTransform t = { - .a = 1, .b = 0, - .c = 0, .d = -1, - .tx = 0, - .ty = dc.portBounds.size.height - }; - - dc.portBounds.origin.x += macDraw->xOff; - dc.portBounds.origin.y += macDraw->yOff; +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXSetupDrawingContext: pushing GState for %s\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); +#endif + CGContextSaveGState(dc.context); CGContextSetTextDrawingMode(dc.context, kCGTextFill); - CGContextConcatCTM(dc.context, t); + { /* Restricted scope for t needed for C++ */ + drawingHeight = view ? [view bounds].size.height : + CGContextGetClipBoundingBox(dc.context).size.height; + CGAffineTransform t = { + .a = 1, .b = 0, + .c = 0, .d = -1, + .tx = 0, + .ty = drawingHeight + }; + CGContextConcatCTM(dc.context, t); + } if (dc.clipRgn) { #ifdef TK_MAC_DEBUG_DRAWING CGContextSaveGState(dc.context); ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); @@ -1352,17 +1361,43 @@ CGContextSetRGBFillColor(dc.context, 1.0, 0.0, 0.0, 0.1); CGContextEOFillPath(dc.context); CGContextRestoreGState(dc.context); #endif /* TK_MAC_DEBUG_DRAWING */ - CGRect r; - CGRect b = CGRectApplyAffineTransform( - CGContextGetClipBoundingBox(dc.context), t); - if (!HIShapeIsRectangular(dc.clipRgn) || - !CGRectContainsRect(*HIShapeGetBounds(dc.clipRgn, &r), b)) { + if (!HIShapeIsRectangular(dc.clipRgn)) { + + /* + * We expect the clipping path dc.clipRgn to consist of the + * bounding rectangle of the drawable window, together with + * disjoint smaller rectangles inside of it which bound its + * geometric children. In that case the even-odd rule will + * clip to the region inside the large rectangle and outside + * of the smaller rectangles. + */ + ChkErr(HIShapeReplacePathInCGContext, dc.clipRgn, dc.context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Setting complex clip for %s to:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None"); + TkMacOSXPrintRectsInRegion(dc.clipRgn); +#endif + CGContextEOClip(dc.context); + } else { + CGRect r; + HIShapeGetBounds(dc.clipRgn, &r); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "Current clip BBox is %s\n", + NSStringFromRect(CGContextGetClipBoundingBox(GET_CGCONTEXT)).UTF8String); + fprintf(stderr, "Setting clip for %s to rect %s:\n", + macDraw->winPtr ? Tk_PathName(macDraw->winPtr) : "None", + NSStringFromRect(r).UTF8String); +#endif + + CGContextClipToRect(dc.context, r); } } if (gc) { static const CGLineCap cgCap[] = { [CapNotLast] = kCGLineCapButt, @@ -1378,12 +1413,12 @@ bool shouldAntialias = !notAA(gc->line_width); double w = gc->line_width; TkMacOSXSetColorInContext(gc, gc->foreground, dc.context); if (view) { - CGContextSetPatternPhase(dc.context, CGSizeMake( - dc.portBounds.size.width, dc.portBounds.size.height)); + CGSize size = NSSizeToCGSize([view bounds].size); + CGContextSetPatternPhase(dc.context, size); } if (gc->function != GXcopy) { TkMacOSXDbgMsg("Logical functions other than GXcopy are " "not supported for CG drawing!"); } @@ -1419,17 +1454,13 @@ } end: #ifdef TK_MAC_DEBUG_DRAWING - if (!canDraw && win != NULL) { - TkWindow *winPtr = TkMacOSXGetTkWindow(win); - - if (winPtr) { - fprintf(stderr, "Cannot draw in %s - postponing.\n", - Tk_PathName(winPtr)); - } + if (!canDraw && macDraw->winPtr != NULL) { + fprintf(stderr, "Cannot draw in %s - postponing.\n", + Tk_PathName(macDraw->winPtr)); } #endif if (!canDraw && dc.clipRgn) { CFRelease(dc.clipRgn); @@ -1460,17 +1491,25 @@ TkMacOSXDrawingContext *dcPtr) { if (dcPtr->context) { CGContextSynchronize(dcPtr->context); CGContextRestoreGState(dcPtr->context); + +#ifdef TK_MAC_DEBUG_CG + fprintf(stderr, "TkMacOSXRestoreDrawingContext: popped GState\n"); +#endif + } if (dcPtr->clipRgn) { CFRelease(dcPtr->clipRgn); + dcPtr->clipRgn = NULL; } + #ifdef TK_MAC_DEBUG bzero(dcPtr, sizeof(TkMacOSXDrawingContext)); -#endif /* TK_MAC_DEBUG */ +#endif + } /* *---------------------------------------------------------------------- * Index: macosx/tkMacOSXEmbed.c ================================================================== --- macosx/tkMacOSXEmbed.c +++ macosx/tkMacOSXEmbed.c @@ -5,13 +5,13 @@ * basic operations needed for application embedding (where one * application can use as its main window an internal window from some * other application). Currently only Toplevel embedding within the same * Tk application is allowed on the Macintosh. * - * Copyright (c) 1996-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -702,11 +702,11 @@ static void EmbeddedEventProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - TkWindow *winPtr = clientData; + TkWindow *winPtr = (TkWindow *)clientData; if (eventPtr->type == DestroyNotify) { EmbedWindowDeleted(winPtr); } } @@ -737,11 +737,11 @@ static void ContainerEventProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - TkWindow *winPtr = clientData; + TkWindow *winPtr = (TkWindow *)clientData; Container *containerPtr; Tk_ErrorHandler errHandler; if (!firstContainerPtr) { /* @@ -845,20 +845,20 @@ static void EmbedStructureProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = clientData; + Container *containerPtr = (Container *)clientData; Tk_ErrorHandler errHandler; if (eventPtr->type == ConfigureNotify) { /* * Send a ConfigureNotify to the embedded application. */ - if (containerPtr->embeddedPtr != None) { + if (containerPtr->embeddedPtr != NULL) { TkDoConfigureNotify(containerPtr->embeddedPtr); } if (containerPtr->embedded != None) { /* * Ignore errors, since the embedded application could have @@ -899,11 +899,11 @@ static void EmbedActivateProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = clientData; + Container *containerPtr = (Container *)clientData; if (containerPtr->embeddedPtr != NULL) { if (eventPtr->type == ActivateNotify) { TkGenerateActivateEvents(containerPtr->embeddedPtr,1); } else if (eventPtr->type == DeactivateNotify) { @@ -934,11 +934,11 @@ static void EmbedFocusProc( ClientData clientData, /* Token for container window. */ XEvent *eventPtr) /* ResizeRequest event. */ { - Container *containerPtr = clientData; + Container *containerPtr = (Container *)clientData; Display *display; XEvent event; if (containerPtr->embeddedPtr != NULL) { display = Tk_Display(containerPtr->parentPtr); @@ -1080,10 +1080,13 @@ */ prevPtr = NULL; containerPtr = firstContainerPtr; while (1) { + if (containerPtr == NULL) { + return; + } if (containerPtr->embeddedPtr == winPtr) { /* * We also have to destroy our parent, to clean up the container. * Fabricate an event to do this. */ Index: macosx/tkMacOSXEntry.c ================================================================== --- macosx/tkMacOSXEntry.c +++ macosx/tkMacOSXEntry.c @@ -1,13 +1,13 @@ /* * tkMacOSXEntry.c -- * * This file implements the native aqua entry widget. * - * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright 2008-2009, Apple Inc. + * Copyright © 2001 Apple Computer, Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2008-2009 Apple Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXEvent.c ================================================================== --- macosx/tkMacOSXEvent.c +++ macosx/tkMacOSXEvent.c @@ -1,13 +1,13 @@ /* * tkMacOSXEvent.c -- * * This file contains the basic Mac OS X Event handling routines. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXFont.c ================================================================== --- macosx/tkMacOSXFont.c +++ macosx/tkMacOSXFont.c @@ -2,13 +2,13 @@ * tkMacOSXFont.c -- * * Contains the Macintosh implementation of the platform-independent font * package interface. * - * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright 2008-2009, Apple Inc. + * Copyright © 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2008-2009 Apple Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -110,11 +110,11 @@ length:(NSUInteger)len { self = [self init]; if (self) { Tcl_DStringInit(&_ds); - Tcl_UtfToChar16DString(bytes, len, &_ds); + Tcl_UtfToChar16DString((const char *)bytes, len, &_ds); _string = [[NSString alloc] initWithCharactersNoCopy:(unichar *)Tcl_DStringValue(&_ds) length:Tcl_DStringLength(&_ds)>>1 freeWhenDone:NO]; self.UTF8String = _string.UTF8String; @@ -125,11 +125,11 @@ - (instancetype)initWithString:(NSString *)aString { self = [self init]; if (self) { _string = [[NSString alloc] initWithString:aString]; - self.UTF8String = _string.UTF8String; + _UTF8String = _string.UTF8String; } return self; } - (void)dealloc @@ -147,14 +147,10 @@ - (unichar)characterAtIndex:(NSUInteger)index { return [_string characterAtIndex:index]; } -# ifndef __clang__ -@synthesize DString = _ds; -#endif - - (Tcl_DString)DString { if ( _ds.string == NULL) { /* @@ -175,10 +171,11 @@ return _ds; } #ifndef __clang__ @synthesize UTF8String = _UTF8String; +@synthesize DString = _ds; #endif @end #define GetNSFontTraitsFromTkFontAttributes(faPtr) \ ((faPtr)->weight == TK_FW_BOLD ? NSBoldFontMask : NSUnboldFontMask) | \ @@ -1207,24 +1204,25 @@ if (!string) { return; } context = drawingContext.context; - fg = TkMacOSXCreateCGColor(gc, gc->foreground); + TkSetMacColor(gc->foreground, &fg); attributes = [fontPtr->nsAttributes mutableCopy]; [attributes setObject:(id)fg forKey:(id)kCTForegroundColorAttributeName]; CFRelease(fg); nsFont = [attributes objectForKey:NSFontAttributeName]; [nsFont setInContext:GET_NSCONTEXT(context, NO)]; CGContextSetTextMatrix(context, CGAffineTransformIdentity); attributedString = [[NSAttributedString alloc] initWithString:string attributes:attributes]; + [string release]; typesetter = CTTypesetterCreateWithAttributedString( (CFAttributedStringRef)attributedString); textX += (CGFloat) macWin->xOff; textY += (CGFloat) macWin->yOff; - height = drawingContext.portBounds.size.height; + height = [drawingContext.view bounds].size.height; textY = height - textY; t = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, height); if (angle != 0.0) { t = CGAffineTransformTranslate( CGAffineTransformRotate( @@ -1252,11 +1250,10 @@ CGContextSetTextPosition(context, textX, textY); CTLineDraw(line, context); CFRelease(line); CFRelease(typesetter); [attributedString release]; - [string release]; [attributes release]; TkMacOSXRestoreDrawingContext(&drawingContext); } #pragma mark - Index: macosx/tkMacOSXFont.h ================================================================== --- macosx/tkMacOSXFont.h +++ macosx/tkMacOSXFont.h @@ -2,14 +2,14 @@ * tkMacOSXFont.h -- * * Contains the Macintosh implementation of the platform-independent * font package interface. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXHLEvents.c ================================================================== --- macosx/tkMacOSXHLEvents.c +++ macosx/tkMacOSXHLEvents.c @@ -1,15 +1,15 @@ /* * tkMacOSXHLEvents.c -- * * Implements high level event support for the Macintosh. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright (c) 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2015-2019 Marc Culler - * Copyright (c) 2019 Kevin Walzer/WordTech Communications LLC. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2015-2019 Marc Culler + * Copyright © 2019 Kevin Walzer/WordTech Communications LLC. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -57,10 +57,11 @@ static const char openDocumentProc[] = "::tk::mac::OpenDocument"; static const char launchURLProc[] = "::tk::mac::LaunchURL"; static const char printDocProc[] = "::tk::mac::PrintDocument"; static const char scriptFileProc[] = "::tk::mac::DoScriptFile"; static const char scriptTextProc[] = "::tk::mac::DoScriptText"; +static const char getSdefProc[] = "::tk::mac::GetDynamicSdef"; #pragma mark TKApplication(TKHLEvents) @implementation TKApplication(TKHLEvents) - (void) terminate: (id) sender @@ -69,10 +70,11 @@ [self handleQuitApplicationEvent:Nil withReplyEvent:Nil]; } - (void) superTerminate: (id) sender { + (void) sender; [super terminate:nil]; } - (void) preferences: (id) sender { @@ -382,10 +384,26 @@ AEInfo->replyEvent = nil; Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); AEInfo->retryCount = 0; ProcessAppleEvent((ClientData)AEInfo); } + +- (void)handleGetSDEFEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { + AppleEventInfo *AEInfo = (AppleEventInfo *)ckalloc(sizeof(AppleEventInfo)); + Tcl_DString *sdefCommand = &AEInfo->command; + (void)replyEvent; + + Tcl_DStringInit(sdefCommand); + Tcl_DStringAppend(sdefCommand, getSdefProc, -1); + AEInfo->interp = _eventInterp; + AEInfo->procedure = getSdefProc; + AEInfo->replyEvent = nil; + Tcl_DoWhenIdle(ProcessAppleEvent, (ClientData)AEInfo); + AEInfo->retryCount = 0; + ProcessAppleEvent((ClientData)AEInfo); + +} @end #pragma mark - @@ -520,10 +538,19 @@ [aeManager setEventHandler:NSApp andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; + /* + * We do not load our sdef dynamically but this event handler + * is required to silence error messages from inline execution + * of AppleScript at the Objective-C level. + */ + [aeManager setEventHandler:NSApp + andSelector:@selector(handleGetSDEFEvent:withReplyEvent:) + forEventClass:'ascr' andEventID:'gsdf']; + } } /* *---------------------------------------------------------------------- Index: macosx/tkMacOSXImage.c ================================================================== --- macosx/tkMacOSXImage.c +++ macosx/tkMacOSXImage.c @@ -2,13 +2,13 @@ * tkMacOSXImage.c -- * * The code in this file provides an interface for XImages, * * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. + * Copyright (c) 2001-2009, Apple Inc. * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2017-2020 Marc Culler. + * Copyright (c) 2017-2021 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -16,10 +16,75 @@ #include "xbytes.h" static CGImageRef CreateCGImageFromPixmap(Drawable pixmap); static CGImageRef CreateCGImageFromDrawableRect( Drawable drawable, int x, int y, unsigned int width, unsigned int height); + +/* Pixel formats + * + * Tk uses the XImage structure defined in Xlib.h for storing images. The + * image data in an XImage is a 32-bit aligned array of bytes. Interpretation + * of that data is not specified, but the structure includes parameters which + * provide interpretation hints so that an application can use a family of + * different data structures. + * + * The possible values for the XImage format field are XYBitmap, XYPixmap and + * ZPixmap. The macOS port does not support the XYPixmap format. This means + * that bitmap images are stored as a single bit plane (XYBitmap) and that + * color images are stored as a sequence of pixel values (ZPixmap). + * + * For a ZPixmap, the number of bits allocated to each pixel is specified by + * the bits_per_pixel field of the XImage structure. The functions in this + * module which convert between XImage and native CGImage or NSImage structures + * only support XImages with 32 bits per pixel. The ImageGetPixel and PutPixel + * implementations in this file allow 1, 4, 8, 16 or 32 bits per pixel, however. + * + * In tkImgPhInstance.c the layout used for pixels is determined by the values + * of the red_mask, blue_mask and green_mask fields in the XImage structure. + * The Aqua port always sets red_mask = 0xFF0000, green_mask = 0xFF00, and + * blue_mask = 0xFF. This means that a 32bpp ZPixmap XImage uses ARGB32 pixels, + * with small-endian byte order BGRA. The data array for such an XImage can be + * passed directly to construct a CGBitmapImageRep if one specifies the + * bitmapInfo as kCGBitmapByteOrder32Big | kCGImageAlphaLast. + * + * The structures below describe the bitfields in two common 32 bpp pixel + * layouts. Note that bit field layouts are compiler dependent. The layouts + * shown in the comments are those produced by clang and gcc. Also note + * that kCGBitmapByteOrder32Big is consistently set when creating CGImages or + * CGImageBitmapReps. + */ + +/* RGBA32 0xRRGGBBAA (Byte order is RGBA on big-endian systems.) + * This is used by NSBitmapImageRep when the bitmapFormat property is 0, + * the default value. + */ + +typedef struct RGBA32pixel_t { + unsigned red: 8; + unsigned green: 8; + unsigned blue: 8; + unsigned alpha: 8; +} RGBA32pixel; + +/* + * ARGB32 0xAARRGGBB (Byte order is ARGB on big-endian systems.) + * This is used by Aqua Tk for XImages and by NSBitmapImageReps whose + * bitmapFormat property is NSBitmapFormatAlphaFirst. + */ + +typedef struct ARGB32pixel_t { + unsigned blue: 8; + unsigned green: 8; + unsigned red: 8; + unsigned alpha: 8; +} ARGB32pixel; + +typedef union pixel32_t { + unsigned int uint; + RGBA32pixel rgba; + ARGB32pixel argb; +} pixel32; #pragma mark XImage handling int _XInitImageFuncPtrs( @@ -53,11 +118,12 @@ ckfree(info); } CGImageRef TkMacOSXCreateCGImageWithXImage( - XImage *image) + XImage *image, + uint32_t alphaInfo) { CGImageRef img = NULL; size_t bitsPerComponent, bitsPerPixel; size_t len = image->bytes_per_line * image->height; const CGFloat *decode = NULL; @@ -84,11 +150,11 @@ while (srcPtr < endPtr) { *destPtr++ = xBitReverseTable[(unsigned char)(*(srcPtr++))]; } } else { - data = memcpy(ckalloc(len), image->data + image->xoffset, len); + data = (char *)memcpy(ckalloc(len), image->data + image->xoffset, len); } if (data) { provider = CGDataProviderCreateWithData(data, data, len, releaseData); } @@ -96,29 +162,29 @@ img = CGImageMaskCreate(image->width, image->height, bitsPerComponent, bitsPerPixel, image->bytes_per_line, provider, decode, 0); } } else if ((image->format == ZPixmap) && (image->bits_per_pixel == 32)) { + /* * Color image */ CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); if (image->width == 0 && image->height == 0) { + /* * CGCreateImage complains on early macOS releases. */ return NULL; } bitsPerComponent = 8; bitsPerPixel = 32; - bitmapInfo = (image->byte_order == MSBFirst ? - kCGBitmapByteOrder32Little : kCGBitmapByteOrder32Big); - bitmapInfo |= kCGImageAlphaLast; - data = memcpy(ckalloc(len), image->data + image->xoffset, len); + bitmapInfo = kCGBitmapByteOrder32Big | alphaInfo; + data = (char *)memcpy(ckalloc(len), image->data + image->xoffset, len); if (data) { provider = CGDataProviderCreateWithData(data, data, len, releaseData); } if (provider) { @@ -203,18 +269,16 @@ + (y * image->bytes_per_line) + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); switch (image->bits_per_pixel) { case 32: /* 8 bits per channel */ - r = (*((unsigned int*) srcPtr) >> 16) & 0xff; - g = (*((unsigned int*) srcPtr) >> 8) & 0xff; - b = (*((unsigned int*) srcPtr) ) & 0xff; - /*if (image->byte_order == LSBFirst) { - r = srcPtr[2]; g = srcPtr[1]; b = srcPtr[0]; - } else { - r = srcPtr[1]; g = srcPtr[2]; b = srcPtr[3]; - }*/ + { + ARGB32pixel *pixel = (ARGB32pixel *)srcPtr; + r = pixel->red; + g = pixel->green; + b = pixel->blue; + } break; case 16: /* 5 bits per channel */ r = (*((unsigned short*) srcPtr) >> 7) & 0xf8; g = (*((unsigned short*) srcPtr) >> 2) & 0xf8; b = (*((unsigned short*) srcPtr) << 3) & 0xf8; @@ -247,11 +311,14 @@ /* *---------------------------------------------------------------------- * * ImagePutPixel -- * - * Set a single pixel in an image. + * Set a single pixel in an image. The pixel is provided as an unsigned + * 32-bit integer. The value of that integer is interpreted by assuming + * that its low-order N bits have the format specified by the XImage, + * where N is equal to the bits_per_pixel field of the XImage. * * Results: * None. * * Side effects: @@ -273,31 +340,24 @@ + (((image->xoffset + x) * image->bits_per_pixel) / NBBY); if (image->bits_per_pixel == 32) { *((unsigned int*) dstPtr) = pixel; } else { - unsigned char r = ((pixel & image->red_mask) >> 16) & 0xff; - unsigned char g = ((pixel & image->green_mask) >> 8) & 0xff; - unsigned char b = ((pixel & image->blue_mask) ) & 0xff; switch (image->bits_per_pixel) { case 16: - *((unsigned short*) dstPtr) = ((r & 0xf8) << 7) | - ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + *((unsigned short*) dstPtr) = pixel & 0xffff; break; case 8: - *dstPtr = ((r & 0xc0) >> 2) | ((g & 0xc0) >> 4) | - ((b & 0xc0) >> 6); + *dstPtr = pixel & 0xff; break; case 4: { - unsigned char c = ((r & 0x80) >> 5) | ((g & 0x80) >> 6) | - ((b & 0x80) >> 7); - *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (c & 0x0f)) : - ((*dstPtr & 0x0f) | ((c << 4) & 0xf0)); + *dstPtr = (x % 2) ? ((*dstPtr & 0xf0) | (pixel & 0x0f)) : + ((*dstPtr & 0x0f) | ((pixel << 4) & 0xf0)); break; } case 1: - *dstPtr = ((r|g|b) & 0x80) ? (*dstPtr | (0x80 >> (x % 8))) : + *dstPtr = pixel ? (*dstPtr | (0x80 >> (x % 8))) : (*dstPtr & ~(0x80 >> (x % 8))); break; } } } @@ -334,11 +394,11 @@ int bytes_per_line) { XImage *ximage; display->request++; - ximage = ckalloc(sizeof(XImage)); + ximage = (XImage *)ckalloc(sizeof(XImage)); ximage->height = height; ximage->width = width; ximage->depth = depth; ximage->xoffset = offset; @@ -390,107 +450,163 @@ } /* *---------------------------------------------------------------------- * - * XPutImage -- + * TkPutImage, XPutImage, TkpPutRGBAImage -- + * + * These functions, which all have the same signature, copy a rectangular + * subimage of an XImage into a drawable. TkPutImage is an alias for + * XPutImage, which assumes that the XImage data has the structure of a + * 32bpp ZPixmap in which the image data is an array of 32bit integers + * packed with 8 bit values for the Red Green and Blue channels. The + * fourth byte is ignored. The function TkpPutRGBAImage assumes that the + * XImage data has been extended by using the fourth byte to store an + * 8-bit Alpha value. (The Alpha data is assumed not to pre-multiplied). + * The image is then drawn into the drawable using standard Porter-Duff + * Source Atop Composition (kCGBlendModeSourceAtop in Apple's Core + * Graphics). * - * Copies a rectangular subimage of an XImage into a drawable. Currently - * this is only called by TkImgPhotoDisplay, using a Window as the - * drawable. + * The TkpPutRGBAImage function is used by TkImgPhotoDisplay to render photo + * images if the compile-time variable TK_CAN_RENDER_RGBA is defined in + * a platform's tkXXXXPort.h header, as is the case for the macOS Aqua port. * * Results: - * None. + * These functions return either BadDrawable or Success. * * Side effects: * Draws the image on the specified drawable. * *---------------------------------------------------------------------- */ -int -XPutImage( +#define USE_ALPHA kCGImageAlphaLast +#define IGNORE_ALPHA kCGImageAlphaNoneSkipLast + +static int +TkMacOSXPutImage( + uint32_t pixelFormat, Display* display, /* Display. */ Drawable drawable, /* Drawable to place image on. */ GC gc, /* GC to use. */ XImage* image, /* Image to place. */ int src_x, /* Source X & Y. */ int src_y, int dest_x, /* Destination X & Y. */ int dest_y, unsigned int width, /* Same width & height for both */ - unsigned int height) /* distination and source. */ + unsigned int height) /* destination and source. */ { TkMacOSXDrawingContext dc; MacDrawable *macDraw = (MacDrawable *)drawable; + int result = Success; display->request++; if (!TkMacOSXSetupDrawingContext(drawable, gc, &dc)) { return BadDrawable; } if (dc.context) { CGRect bounds, srcRect, dstRect; - CGImageRef img = TkMacOSXCreateCGImageWithXImage(image); + CGImageRef img = TkMacOSXCreateCGImageWithXImage(image, pixelFormat); /* * The CGContext for a pixmap is RGB only, with A = 0. */ if (!(macDraw->flags & TK_IS_PIXMAP)) { CGContextSetBlendMode(dc.context, kCGBlendModeSourceAtop); } if (img) { - bounds = CGRectMake(0, 0, image->width, image->height); srcRect = CGRectMake(src_x, src_y, width, height); dstRect = CGRectMake(dest_x, dest_y, width, height); TkMacOSXDrawCGImage(drawable, gc, dc.context, img, gc->foreground, gc->background, bounds, srcRect, dstRect); CFRelease(img); } else { TkMacOSXDbgMsg("Invalid source drawable"); + result = BadDrawable; } } else { TkMacOSXDbgMsg("Invalid destination drawable"); + result = BadDrawable; } TkMacOSXRestoreDrawingContext(&dc); - return Success; + return result; +} + +int XPutImage( + Display* display, + Drawable drawable, + GC gc, + XImage* image, + int src_x, + int src_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height) { + return TkMacOSXPutImage(IGNORE_ALPHA, display, drawable, gc, image, + src_x, src_y, dest_x, dest_y, width, height); +} + +int TkpPutRGBAImage( + Display* display, + Drawable drawable, + GC gc, + XImage* image, + int src_x, + int src_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height) { + return TkMacOSXPutImage(USE_ALPHA, display, drawable, gc, image, + src_x, src_y, dest_x, dest_y, width, height); } + /* *---------------------------------------------------------------------- * * CreateCGImageFromDrawableRect * - * Extract image data from a MacOSX drawable as a CGImage. - * - * This is only called by XGetImage and XCopyArea. The Tk core uses - * these functions on some platforms, but on macOS the core does not - * call them with a source drawable which is a window. Such calls are - * used only for double-buffered drawing. Since macOS defines the - * macro TK_NO_DOUBLE_BUFFERING, the generic code never calls XGetImage - * or XCopyArea on macOS. Nonetheless, these function are in the stubs - * table and therefore could be used by extensions. - * - * This implementation does not work correctly. Originally it relied on + * Extract image data from a MacOSX drawable as a CGImage. The drawable + * may be either a pixmap or a window, but there issues in the case of + * a window. + * + * CreateCGImageFromDrawableRect is called by XGetImage and XCopyArea. + * The Tk core uses these two functions on some platforms in order to + * implement explicit double-buffered drawing -- a pixmap is copied from a + * window, modified using CPU-based graphics composition, and then copied + * back to the window. Platforms, such as macOS, on which the system + * provides double-buffered drawing and GPU-based composition operations + * can avoid calls to XGetImage and XCopyArea from the core by defining + * the compile-time variable TK_NO_DOUBLE_BUFFERING. Nonetheless, these + * two functions are in the stubs table and therefore could be used by + * extensions. + * + * The implementation here does not always work correctly when the source + * is a window. The original version of this function relied on * [NSBitmapImageRep initWithFocusedViewRect:view_rect] which was * deprecated by Apple in OSX 10.14 and also required the use of other * deprecated functions such as [NSView lockFocus]. Apple's suggested * replacement is [NSView cacheDisplayInRect: toBitmapImageRep:] and that - * is what is being used here. However, that method only works when the - * view has a valid CGContext, and a view is only guaranteed to have a - * valid context during a call to [NSView drawRect]. To further complicate - * matters, cacheDisplayInRect calls [NSView drawRect]. Essentially it is - * asking the view to draw a subrectangle of itself using a special - * graphics context which is linked to the BitmapImageRep. But our - * implementation of [NSView drawRect] does not allow recursive calls. If - * called recursively it returns immediately without doing any drawing. - * So the bottom line is that this function either returns a NULL pointer - * or a black image. To make it useful would require a significant amount - * of rewriting of the drawRect method. Perhaps the next release of OSX - * will include some more helpful ways of doing this. + * is being used here. However, cacheDisplayInRect works by calling + * [NSView drawRect] after setting the current graphics context to be one + * which draws to a bitmap. There are situations in which this can be + * used, e.g. when taking a screenshot of a window. But it cannot be used + * as part of a normal display procedure, using the copy-modify-paste + * paradigm that is the basis of the explicit double-buffering. Since the + * copy operation will call the same display procedure that is calling + * this function via XGetImage or XCopyArea, this would create an infinite + * recursion. + * + * An alternative to the copy-modify-paste paradigm is to use GPU-based + * graphics composition, clipping to the specified rectangle. That is + * the approach that must be followed by display procedures on macOS. * * Results: * Returns an NSBitmapRep representing the image of the given rectangle of * the given drawable. This object is retained. The caller is responsible * for releasing it. @@ -513,55 +629,47 @@ unsigned int width, unsigned int height) { MacDrawable *mac_drawable = (MacDrawable *)drawable; CGContextRef cg_context = NULL; + CGRect image_rect = CGRectMake(x, y, width, height); CGImageRef cg_image = NULL, result = NULL; - NSBitmapImageRep *bitmapRep = NULL; - NSView *view = NULL; + unsigned char *imageData = NULL; if (mac_drawable->flags & TK_IS_PIXMAP) { - /* - * This MacDrawable is a bitmap, so its view is NULL. - */ - - CGRect image_rect = CGRectMake(x, y, width, height); - cg_context = TkMacOSXGetCGContextForDrawable(drawable); - cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); - if (cg_image) { - result = CGImageCreateWithImageInRect(cg_image, image_rect); - CGImageRelease(cg_image); - } - } else if (TkMacOSXGetNSViewForDrawable(mac_drawable) != NULL) { - - /* - * Convert Tk top-left to NSView bottom-left coordinates. - */ - - int view_height = [view bounds].size.height; - NSRect view_rect = NSMakeRect(x + mac_drawable->xOff, - view_height - height - y - mac_drawable->yOff, - width, height); - - /* - * Attempt to copy from the view to a bitmapImageRep. If the view does - * not have a valid CGContext, doing this will silently corrupt memory - * and make a big mess. So, in that case, we just return NULL. - */ - - if (view == [NSView focusView]) { - bitmapRep = [view bitmapImageRepForCachingDisplayInRect: view_rect]; - [view cacheDisplayInRect:view_rect toBitmapImageRep:bitmapRep]; - result = [bitmapRep CGImage]; - CFRelease(bitmapRep); - } else { - TkMacOSXDbgMsg("No CGContext - cannot copy from screen to bitmap."); - result = NULL; - } - } else { - TkMacOSXDbgMsg("Invalid source drawable"); - } + if (cg_context) { + cg_image = CGBitmapContextCreateImage((CGContextRef) cg_context); + } + } else { + NSView *view = TkMacOSXGetNSViewForDrawable(mac_drawable); + if (view == nil) { + TkMacOSXDbgMsg("Invalid source drawable"); + return NULL; + } + NSSize size = view.frame.size; + NSUInteger view_width = size.width, view_height = size.height; + NSUInteger bytesPerPixel = 4, + bytesPerRow = bytesPerPixel * view_width, + bitsPerComponent = 8; + imageData = ckalloc(view_height * bytesPerRow); + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + cg_context = CGBitmapContextCreate(imageData, view_width, view_height, + bitsPerComponent, bytesPerRow, colorSpace, + kCGImageAlphaPremultipliedLast | + kCGBitmapByteOrder32Big); + CFRelease(colorSpace); + [view.layer renderInContext:cg_context]; + } + if (cg_context) { + cg_image = CGBitmapContextCreateImage(cg_context); + CGContextRelease(cg_context); + } + if (cg_image) { + result = CGImageCreateWithImageInRect(cg_image, image_rect); + CGImageRelease(cg_image); + } + ckfree(imageData); return result; } /* *---------------------------------------------------------------------- @@ -612,13 +720,10 @@ * Side effects: * None. * *---------------------------------------------------------------------- */ -struct pixel_fmt {int r; int g; int b; int a;}; -static struct pixel_fmt bgra = {2, 1, 0, 3}; -static struct pixel_fmt abgr = {3, 2, 1, 0}; XImage * XGetImage( Display *display, Drawable drawable, @@ -627,15 +732,14 @@ unsigned int width, unsigned int height, TCL_UNUSED(unsigned long), /* plane_mask */ int format) { - NSBitmapImageRep* bitmapRep = NULL; + NSBitmapImageRep* bitmapRep = nil; NSUInteger bitmap_fmt = 0; XImage* imagePtr = NULL; - char* bitmap = NULL; - char R, G, B, A; + char *bitmap = NULL; int depth = 32, offset = 0, bitmap_pad = 0; unsigned int bytes_per_row, size, row, n, m; if (format == ZPixmap) { CGImageRef cgImage; @@ -653,53 +757,54 @@ return NULL; } bitmap_fmt = [bitmapRep bitmapFormat]; size = [bitmapRep bytesPerPlane]; bytes_per_row = [bitmapRep bytesPerRow]; - bitmap = ckalloc(size); - if (!bitmap - || (bitmap_fmt != 0 && bitmap_fmt != 1) - || [bitmapRep samplesPerPixel] != 4 - || [bitmapRep isPlanar] != 0 - || bytes_per_row < 4 * width - || size != bytes_per_row * height) { + bitmap = (char *)ckalloc(size); + if ((bitmap_fmt != 0 && bitmap_fmt != NSBitmapFormatAlphaFirst) + || [bitmapRep samplesPerPixel] != 4 + || [bitmapRep isPlanar] != 0 + || bytes_per_row < 4 * width + || size != bytes_per_row * height) { TkMacOSXDbgMsg("XGetImage: Unrecognized bitmap format"); - CFRelease(bitmapRep); + [bitmapRep release]; return NULL; } memcpy(bitmap, (char *)[bitmapRep bitmapData], size); - CFRelease(bitmapRep); - - /* - * When Apple extracts a bitmap from an NSView, it may be in either - * BGRA or ABGR format. For an XImage we need RGBA. - */ - - struct pixel_fmt pixel = bitmap_fmt == 0 ? bgra : abgr; + [bitmapRep release]; for (row = 0, n = 0; row < height; row++, n += bytes_per_row) { for (m = n; m < n + 4*width; m += 4) { - R = *(bitmap + m + pixel.r); - G = *(bitmap + m + pixel.g); - B = *(bitmap + m + pixel.b); - A = *(bitmap + m + pixel.a); - - *(bitmap + m) = R; - *(bitmap + m + 1) = G; - *(bitmap + m + 2) = B; - *(bitmap + m + 3) = A; + pixel32 pixel = *((pixel32 *)(bitmap + m)); + if (bitmap_fmt == 0) { // default format + + /* + * This pixel is in ARGB32 format. We need RGBA32. + */ + + pixel32 flipped; + flipped.rgba.red = pixel.argb.red; + flipped.rgba.green = pixel.argb.green; + flipped.rgba.blue = pixel.argb.blue; + flipped.rgba.alpha = pixel.argb.alpha; + *((pixel32 *)(bitmap + m)) = flipped; + } else { // bitmap_fmt = NSBitmapFormatAlphaFirst + *((pixel32 *)(bitmap + m)) = pixel; + } } } imagePtr = XCreateImage(display, NULL, depth, format, offset, (char*) bitmap, width, height, bitmap_pad, bytes_per_row); } else { + /* * There are some calls to XGetImage in the generic Tk code which pass * an XYPixmap rather than a ZPixmap. XYPixmaps should be handled * here. */ + TkMacOSXDbgMsg("XGetImage does not handle XYPixmaps at the moment."); } return imagePtr; } Index: macosx/tkMacOSXInit.c ================================================================== --- macosx/tkMacOSXInit.c +++ macosx/tkMacOSXInit.c @@ -2,14 +2,14 @@ * tkMacOSXInit.c -- * * This file contains Mac OS X -specific interpreter initialization * functions. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2017 Marc Culler + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2017 Marc Culler * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -39,10 +39,11 @@ @implementation TKApplication @synthesize poolLock = _poolLock; @synthesize macOSVersion = _macOSVersion; @synthesize isDrawing = _isDrawing; @synthesize needsToDraw = _needsToDraw; +@synthesize isSigned = _isSigned; @end /* * #define this to see a message on stderr whenever _resetAutoreleasePool is * called while the pool is locked. @@ -102,32 +103,53 @@ selector:@selector(_postedNotification:) name:nil object:nil]; #endif [self _setupWindowNotifications]; [self _setupApplicationNotifications]; - /* - * Construct the menu bar. - */ - _defaultMainMenu = nil; - [self _setupMenus]; - - /* - * Initialize event processing. - */ + if ([NSApp macOSVersion] >= 110000) { + + /* + * Initialize Apple Event processing. Apple's docs (see + * https://developer.apple.com/documentation/appkit/nsapplication) + * recommend doing this here, although historically we have + * done this in applicationWillFinishLaunching. In response to + * bug 7bb246b072. + */ + + TkMacOSXInitAppleEvents(_eventInterp); + + } +} + +-(void)applicationDidFinishLaunching:(NSNotification *)notification +{ + (void)notification; + + if ([NSApp macOSVersion] < 110000) { + + /* + * Initialize Apple Event processing on macOS versions + * older than Big Sur (11). + */ TkMacOSXInitAppleEvents(_eventInterp); + + } + /* * Initialize the graphics context. */ TkMacOSXUseAntialiasedText(_eventInterp, -1); TkMacOSXInitCGDrawing(_eventInterp, TRUE, 0); -} --(void)applicationDidFinishLaunching:(NSNotification *)notification -{ - (void)notification; + /* + * Construct the menu bar. + */ + + _defaultMainMenu = nil; + [self _setupMenus]; /* * It is not safe to force activation of the NSApp until this method is * called. Activating too early can cause the menu bar to be unresponsive. * The call to activateIgnoringOtherApps was moved here to avoid this. @@ -200,10 +222,11 @@ if (!iconFile) { NSString *path = [NSApp tkFrameworkImagePath:@"Tk.icns"]; if (path) { NSImage *image = [[NSImage alloc] initWithContentsOfFile:path]; if (image) { + [image setName:@"NSApplicationIcon"]; [NSApp setApplicationIconImage:image]; [image release]; } } } @@ -560,10 +583,12 @@ TkMacOSXStandardAboutPanelObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::tk::mac::iconBitmap", TkMacOSXIconBitmapObjCmd, NULL, NULL); Tcl_CreateObjCommand(interp, "::tk::mac::GetAppPath", TkMacOSXGetAppPathCmd, NULL, NULL); + MacSystrayInit(interp); + MacPrint_Init(interp); return TCL_OK; } /* Index: macosx/tkMacOSXInt.h ================================================================== --- macosx/tkMacOSXInt.h +++ macosx/tkMacOSXInt.h @@ -22,11 +22,13 @@ * Include platform specific public interfaces. */ #ifndef _TKMAC #include "tkMacOSX.h" +#define Cursor QDCursor #import +#undef Cursor #endif /* * Define compatibility platform types used in the structures below so that * this header can be included without pulling in the platform headers. @@ -96,25 +98,10 @@ * still tell what the correct port is after the TKWindow structure has been * freed. This actually happens when you bind destroy of a toplevel to * Destroy of a child. */ -/* - * GC CGColorRef cache for tkMacOSXColor.c - */ - -typedef struct { - unsigned long cachedForeground; - CGColorRef cachedForegroundColor; - unsigned long cachedBackground; - CGColorRef cachedBackgroundColor; -} TkpGCCache; - -MODULE_SCOPE TkpGCCache *TkpGetGCCache(GC gc); -MODULE_SCOPE void TkpInitGCCache(GC gc); -MODULE_SCOPE void TkpFreeGCCache(GC gc); - /* * Undef compatibility platform types defined above. */ #ifndef _TKMACPRIV Index: macosx/tkMacOSXKeyEvent.c ================================================================== --- macosx/tkMacOSXKeyEvent.c +++ macosx/tkMacOSXKeyEvent.c @@ -2,14 +2,14 @@ * tkMacOSXKeyEvent.c -- * * This file implements functions that decode & handle keyboard events on * MacOS X. * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2012 Adrian Robert. - * Copyright 2015-2020 Marc Culler. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2012 Adrian Robert. + * Copyright © 2015-2020 Marc Culler. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -51,11 +51,11 @@ #endif NSWindow *w = [theEvent window]; TkWindow *winPtr = TkMacOSXGetTkWindow(w), *grabWinPtr, *focusWinPtr; Tk_Window tkwin = (Tk_Window)winPtr; NSEventType type = [theEvent type]; - NSUInteger virtual = [theEvent keyCode]; + NSUInteger virt = [theEvent keyCode]; NSUInteger modifiers = ([theEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask); XEvent xEvent; MacKeycode macKC; UniChar keychar = 0; @@ -68,10 +68,22 @@ processingCompose = NO; } if (!winPtr) { return theEvent; } + + /* + * Discard repeating KeyDown events if the repeat speed has been set to + * "off" in System Preferences. It is unclear why we get these, but we do. + * See ticket [2ecb09d118]. + */ + + if ([theEvent type] == NSKeyDown && + [theEvent isARepeat] && + [NSEvent keyRepeatDelay] < 0) { + return theEvent; + } /* * If a local grab is in effect, key events for windows in the * grabber's application are redirected to the grabber. Key events * for other applications are delivered normally. If a global @@ -80,40 +92,50 @@ grabWinPtr = winPtr->dispPtr->grabWinPtr; if (grabWinPtr) { if (winPtr->dispPtr->grabFlags || /* global grab */ grabWinPtr->mainPtr == winPtr->mainPtr){ /* same application */ - winPtr =winPtr->dispPtr->focusPtr; + winPtr = winPtr->dispPtr->focusPtr; + if (!winPtr) { + return theEvent; + } tkwin = (Tk_Window)winPtr; } } /* * Extract the unicode character from KeyUp and KeyDown events. */ if (type == NSKeyUp || type == NSKeyDown) { - if ([[theEvent characters] length] > 0) { - keychar = [[theEvent characters] characterAtIndex:0]; + NSString *characters = [theEvent characters]; + if (characters.length > 0) { + keychar = [characters characterAtIndex:0]; /* * Currently, real keys always send BMP characters, but who knows? */ if (CFStringIsSurrogateHighCharacter(keychar)) { - UniChar lowChar = [[theEvent characters] characterAtIndex:1]; + UniChar lowChar = [characters characterAtIndex:1]; keychar = CFStringGetLongCharacterForSurrogatePair( keychar, lowChar); } } else { /* - * This is a dead key, such as Option-e, so it should go to the - * TextInputClient. + * This is a dead key, such as Option-e, so it usually should get + * passed to the TextInputClient. But if it has a Command modifier + * then it is not functioning as a dead key and should not be + * handled by the TextInputClient. See ticket [1626ed65b8] and the + * method performKeyEquivalent which is implemented in + * tkMacOSXMenu.c. */ - use_text_input = YES; + if (!(modifiers & NSCommandKeyMask)) { + use_text_input = YES; + } } /* * Apple uses 0x10 for unrecognized keys. */ @@ -124,11 +146,11 @@ #if defined(TK_MAC_DEBUG_EVENTS) || NS_KEYLOG == 1 TKLog(@"-[%@(%p) %s] repeat=%d mods=%x char=%x code=%lu c=%d type=%d", [self class], self, _cmd, (type == NSKeyDown) && [theEvent isARepeat], modifiers, keychar, - virtual, w, type); + virt, w, type); #endif } /* @@ -213,11 +235,11 @@ * finish constructing the XEvent and queue it. */ macKC.v.o_s = ((modifiers & NSShiftKeyMask ? INDEX_SHIFT : 0) | (modifiers & NSAlternateKeyMask ? INDEX_OPTION : 0)); - macKC.v.virtual = virtual; + macKC.v.virt = virt; switch (type) { case NSFlagsChanged: /* * This XEvent is a simulated KeyPress or KeyRelease event for a @@ -253,11 +275,10 @@ * Finally we can queue the XEvent, inserting a KeyRelease before a * repeated KeyPress. */ if (type == NSKeyDown && [theEvent isARepeat]) { - xEvent.xany.type = KeyRelease; Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); xEvent.xany.type = KeyPress; } Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); @@ -266,11 +287,11 @@ @end @implementation TKContentView @synthesize tkDirtyRect = _tkDirtyRect; -@synthesize tkNeedsDisplay = _tkNeedsDisplay;; +@synthesize tkNeedsDisplay = _tkNeedsDisplay; /* * Implementation of the NSTextInputClient protocol. */ @@ -347,13 +368,13 @@ macKC.v.keychar = keychar; if (CFStringIsSurrogateHighCharacter(keychar)) { UniChar lowChar = [str characterAtIndex:++i]; macKC.v.keychar = CFStringGetLongCharacterForSurrogatePair( (UniChar)keychar, lowChar); - macKC.v.virtual = NON_BMP_VIRTUAL; + macKC.v.virt = NON_BMP_VIRTUAL; } else if (repRange.location == 0 || sendingIMEText) { - macKC.v.virtual = REPLACEMENT_VIRTUAL; + macKC.v.virt = REPLACEMENT_VIRTUAL; } else { macKC.uint = TkMacOSXAddVirtual(macKC.uint); xEvent.xkey.state |= INDEX2STATE(macKC.x.xvirtual); } keystr = [[NSString alloc] initWithCharacters:&keychar length:1]; @@ -602,15 +623,16 @@ static void setupXEvent(XEvent *xEvent, Tk_Window tkwin, NSUInteger modifiers) { unsigned int state = 0; - Display *display = Tk_Display(tkwin); + Display *display; if (tkwin == NULL) { return; } + display = Tk_Display(tkwin); if (modifiers) { state = (modifiers & NSAlphaShiftKeyMask ? LockMask : 0) | (modifiers & NSShiftKeyMask ? ShiftMask : 0) | (modifiers & NSControlKeyMask ? ControlMask : 0) | (modifiers & NSCommandKeyMask ? Mod1Mask : 0) | @@ -703,12 +725,16 @@ if (keyboardGrabWinPtr && captureWinPtr) { NSWindow *w = TkMacOSXGetNSWindowForDrawable(grab_window); MacDrawable *macWin = (MacDrawable *)grab_window; if (w && macWin->toplevel->winPtr == (TkWindow *) captureWinPtr) { - if (modalSession) { - Tcl_Panic("XGrabKeyboard: already grabbed"); + if (modalSession ) { + if (keyboardGrabNSWindow == w) { + return GrabSuccess; + } else { + Tcl_Panic("XGrabKeyboard: already grabbed"); + } } keyboardGrabNSWindow = w; [w retain]; modalSession = [NSApp beginModalSessionForWindow:w]; } Index: macosx/tkMacOSXKeyboard.c ================================================================== --- macosx/tkMacOSXKeyboard.c +++ macosx/tkMacOSXKeyboard.c @@ -1,14 +1,14 @@ /* * tkMacOSXKeyboard.c -- * * Routines to support keyboard events on the Macintosh. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2020 Marc Culler + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2020 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -141,11 +141,11 @@ */ static void InitHashTables(void); static void UpdateKeymaps(void); static int KeyDataToUnicode(UniChar *uniChars, int maxChars, - UInt16 keyaction, UInt32 virtual, UInt32 modifiers, + UInt16 keyaction, UInt32 virt, UInt32 modifiers, UInt32 * deadKeyStatePtr); #pragma mark TKApplication(TKKeyboard) @implementation TKApplication(TKKeyboard) @@ -186,19 +186,19 @@ const KeysymInfo *ksPtr; int dummy, index; Tcl_InitHashTable(&special2keysym, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&keysym2keycode, TCL_ONE_WORD_KEYS); - for (kPtr = keyArray; kPtr->virtual != 0; kPtr++) { + for (kPtr = keyArray; kPtr->virt != 0; kPtr++) { MacKeycode macKC; macKC.v.o_s = 0; - hPtr = Tcl_CreateHashEntry(&special2keysym, INT2PTR(kPtr->virtual), + hPtr = Tcl_CreateHashEntry(&special2keysym, INT2PTR(kPtr->virt), &dummy); Tcl_SetHashValue(hPtr, INT2PTR(kPtr->keysym)); hPtr = Tcl_CreateHashEntry(&keysym2keycode, INT2PTR(kPtr->keysym), &dummy); - macKC.v.virtual = kPtr->virtual; + macKC.v.virt = kPtr->virt; macKC.v.keychar = kPtr->keychar; Tcl_SetHashValue(hPtr, INT2PTR(macKC.uint)); /* * The Carbon framework does not work for finding the unicode character @@ -250,11 +250,11 @@ static void UpdateKeymaps() { static Bool keymapInitialized = false; Tcl_HashEntry *hPtr; - int virtual, index, dummy; + int virt, index, dummy; if (!keymapInitialized) { Tcl_InitHashTable(&unichar2xvirtual, TCL_ONE_WORD_KEYS); keymapInitialized = true; } else { @@ -266,16 +266,16 @@ * minimal modifier mask. Simpler combinations will overwrite more complex * ones when constructing the table. */ for (index = 3; index >= 0; index--) { - for (virtual = 0; virtual < 128; virtual++) { + for (virt = 0; virt < 128; virt++) { MacKeycode macKC; - macKC.v = (keycode_v) {.virtual = virtual, .o_s = index, .keychar = 0}; + macKC.v = (keycode_v) {.virt = virt, .o_s = index, .keychar = 0}; int modifiers = INDEX2CARBON(index), result; UniChar keychar = 0; - result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virtual, + result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, virt, modifiers, NULL); if (keychar == 0x10) { /* * This is a special key, handled in InitHashTables. @@ -282,11 +282,11 @@ */ continue; } macKC.v.keychar = keychar; - if (! ON_KEYPAD(virtual)) { + if (! ON_KEYPAD(virt)) { hPtr = Tcl_CreateHashEntry(&unichar2xvirtual, INT2PTR(macKC.x.keychar), &dummy); Tcl_SetHashValue(hPtr, INT2PTR(macKC.x.xvirtual)); } xvirtual2unichar[macKC.x.xvirtual] = macKC.x.keychar; @@ -324,11 +324,11 @@ static int KeyDataToUnicode( UniChar *uniChars, int maxChars, UInt16 keyaction, - UInt32 virtual, + UInt32 virt, UInt32 modifiers, UInt32 *deadKeyStatePtr) { static const void *layoutData = NULL; static UInt32 keyboardType = 0; @@ -353,18 +353,18 @@ if (layoutData) { OptionBits options = 0; UInt32 dummyState; OSStatus err; - virtual &= 0xFF; + virt &= 0xFF; modifiers = (modifiers >> 8) & 0xFF; if (!deadKeyStatePtr) { options = kUCKeyTranslateNoDeadKeysMask; dummyState = 0; deadKeyStatePtr = &dummyState; } - err = ChkErr(UCKeyTranslate, layoutData, virtual, keyaction, modifiers, + err = ChkErr(UCKeyTranslate, (const UCKeyboardLayout *)layoutData, virt, keyaction, modifiers, keyboardType, options, deadKeyStatePtr, maxChars, &actuallength, uniChars); if (!actuallength && *deadKeyStatePtr) { /* @@ -422,11 +422,11 @@ /* * First check if the virtual keycode corresponds to a special key, such as * an Fn function key or Tab, Backspace, Home, End, etc. */ - hPtr = Tcl_FindHashEntry(&special2keysym, INT2PTR(macKC.v.virtual)); + hPtr = Tcl_FindHashEntry(&special2keysym, INT2PTR(macKC.v.virt)); if (hPtr != NULL) { return (KeySym) Tcl_GetHashValue(hPtr); } /* @@ -433,11 +433,11 @@ * If the virtual value in this keycode does not correspond to an actual * key in the current keyboard layout, try using its keychar to look up a * keysym. */ - if (macKC.v.virtual > 127) { + if (macKC.v.virt > 127) { hPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(macKC.v.keychar)); if (hPtr != NULL) { return (KeySym) Tcl_GetHashValue(hPtr); } } @@ -448,11 +448,11 @@ * Framework; then translate the keychar to a keysym using the * unicode2keysym hash table. */ modifiers = INDEX2CARBON(macKC.v.o_s); - result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, macKC.v.virtual, + result = KeyDataToUnicode(&keychar, 1, kUCKeyActionDown, macKC.v.virt, modifiers, NULL); if (result) { hPtr = Tcl_FindHashEntry(&unichar2keysym, INT2PTR(keychar)); if (hPtr != NULL) { return (KeySym) Tcl_GetHashValue(hPtr); @@ -635,19 +635,19 @@ * First check for a special key. */ hPtr = Tcl_FindHashEntry(&keysym2keycode, INT2PTR(keysym)); if (hPtr != NULL) { - return (KeyCode) Tcl_GetHashValue(hPtr); + return (KeyCode) PTR2INT(Tcl_GetHashValue(hPtr)); } /* * Initialize the keycode as if the keysym cannot be converted to anything * else. */ - macKC.v.virtual = NO_VIRTUAL; + macKC.v.virt = NO_VIRTUAL; macKC.v.o_s = 0; macKC.v.keychar = 0; /* * If the keysym is recognized fill in the keychar. Also fill in the @@ -717,11 +717,11 @@ macKC.v.o_s |= eventIndex; } if (macKC.v.keychar < 0xF700) { UniChar keychar = macKC.v.keychar; NSString *str, *lower, *upper; - if (macKC.v.virtual != NO_VIRTUAL) { + if (macKC.v.virt != NO_VIRTUAL) { macKC.x.keychar = xvirtual2unichar[macKC.x.xvirtual]; } else { str = [[NSString alloc] initWithCharacters:&keychar length:1]; lower = [str lowercaseString]; upper = [str uppercaseString]; @@ -779,11 +779,11 @@ /* * Modifier key events have a special mac keycode (see tkProcessKeyEvent). */ if (macKC.v.keychar == MOD_KEYCHAR) { - switch (macKC.v.virtual) { + switch (macKC.v.virt) { case 54: return XK_Meta_R; case 55: return XK_Meta_L; case 56: @@ -951,11 +951,11 @@ INT2PTR(macKC.v.keychar)); if (hPtr != NULL) { unsigned long data = (unsigned long) Tcl_GetHashValue(hPtr); macKC.x.xvirtual = (unsigned int) data; } else { - macKC.v.virtual = NO_VIRTUAL; + macKC.v.virt = NO_VIRTUAL; } return macKC.uint; } /* * Local Variables: Index: macosx/tkMacOSXKeysyms.h ================================================================== --- macosx/tkMacOSXKeysyms.h +++ macosx/tkMacOSXKeysyms.h @@ -2,15 +2,15 @@ * tkMacOSXKeysyms.h -- * * Contains data used for processing key events, some of which was * moved from tkMacOSXKeyboard.c. * - * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2020 Marc Culler + * Copyright © 1990-1994 The Regents of the University of California. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2020 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -29,11 +29,11 @@ * as F20, which is reported to be usable in scripts even though it does not * appear on any Macintosh keyboard. */ typedef struct { - int virtual; /* value of [NSEvent keyCode] */ + int virt; /* value of [NSEvent keyCode] */ KeySym keysym; /* X11 keysym */ KeyCode keychar; /* XEvent keycode & 0xFFFF */ } KeyInfo; static const KeyInfo keyArray[] = { Index: macosx/tkMacOSXMenu.c ================================================================== --- macosx/tkMacOSXMenu.c +++ macosx/tkMacOSXMenu.c @@ -1,14 +1,14 @@ /* * tkMacOSXMenu.c -- * * This module implements the Mac-platform specific features of menus. * - * Copyright (c) 1996-1997 by Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2012 Adrian Robert. + * Copyright © 1996-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2012 Adrian Robert. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -187,10 +187,38 @@ } - (BOOL) isSpecial: (NSUInteger) special { return (_tkSpecial == special); } + +/* + * There are cases where a KeyEquivalent (aka menu accelerator) is defined for + * a "dead key", i.e. a key which does not have an associated character but is + * only meant to be the start of a composition sequence. For example, on a + * Spanish keyboard both the ' and the ` keys are dead keys used to place + * accents over letters. But ⌘` is a standard KeyEquivalent which cycles + * through the open windows of an application, changing the focus to the next + * window. + * + * The performKeyEquivalent callback method is being overridden here to work + * around a bug reported in [1626ed65b8]. When a dead key that is also as a + * KeyEquivalent is pressed, a KeyDown event with no characters is passed to + * performKeyEquivalent. The default implementation provided by Apple will + * cause that event to be routed to some private methods of NSMenu which raise + * NSInvalidArgumentException, causing an abort. Returning NO in such a case + * prevents the abort, but does not prevent the KeyEquivalent action from being + * invoked, presumably because the event does get correctly handled higher in + * the responder chain. + */ + +- (BOOL)performKeyEquivalent:(NSEvent *)event +{ + if (event.characters.length == 0) { + return NO; + } + return [super performKeyEquivalent:event]; +} @end @implementation TKMenu(TKMenuPrivate) - (id) initWithTitle: (NSString *) aTitle @@ -231,11 +259,11 @@ return copy; } - (TkMenu *) tkMenu { - return _tkMenu; + return (TkMenu *)_tkMenu; } - (int) tkIndexOfItem: (NSMenuItem *) menuItem { return [self indexOfItem:menuItem] - _tkOffset; @@ -314,16 +342,10 @@ TkMenuEntry *mePtr = (TkMenuEntry *) [menuItem tag]; if (menuPtr && mePtr) { Tcl_Interp *interp = menuPtr->interp; - /* - * Add time for errors to fire if necessary. This is sub-optimal - * but avoids issues with Tcl/Cocoa event loop integration. - */ - - //Tcl_Sleep(100); Tcl_Preserve(interp); Tcl_Preserve(menuPtr); int result = TkInvokeMenu(interp, menuPtr, mePtr->index); @@ -414,11 +436,11 @@ - (void) menuDidClose: (NSMenu *) menu { (void)menu; if (_tkMenu) { - RecursivelyClearActiveMenu(_tkMenu); + RecursivelyClearActiveMenu((TkMenu *)_tkMenu); } } - (void) menu: (NSMenu *) menu willHighlightItem: (NSMenuItem *) item { @@ -438,11 +460,11 @@ Tcl_Interp *interp = menuPtr->interp; Tcl_Preserve(interp); Tcl_Preserve(menuPtr); - int result = TkPostCommand(_tkMenu); + int result = TkPostCommand(menuPtr); if (result!=TCL_OK && result!=TCL_CONTINUE && result!=TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (menu preprocess)"); Tcl_BackgroundException(interp, result); } @@ -683,11 +705,10 @@ NSAttributedString *attributedTitle = nil; NSImage *image = nil; NSString *keyEquivalent = @""; NSUInteger modifierMask = NSCommandKeyMask; NSMenu *submenu = nil; - NSDictionary *attributes; int imageWidth, imageHeight; GC gc = (mePtr->textGC ? mePtr->textGC : mePtr->menuPtr->textGC); Tcl_Obj *fontPtr = (mePtr->fontPtr ? mePtr->fontPtr : mePtr->menuPtr->fontPtr); static unsigned long defaultBg, defaultFg; @@ -704,21 +725,19 @@ if (mePtr->image) { Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); image = TkMacOSXGetNSImageFromTkImage(mePtr->menuPtr->display, mePtr->image, imageWidth, imageHeight); - } else if (mePtr->bitmapPtr != None) { + } else if (mePtr->bitmapPtr != NULL) { Pixmap bitmap = Tk_GetBitmapFromObj(mePtr->menuPtr->tkwin, mePtr->bitmapPtr); Tk_SizeOfBitmap(mePtr->menuPtr->display, bitmap, &imageWidth, &imageHeight); image = TkMacOSXGetNSImageFromBitmap(mePtr->menuPtr->display, bitmap, gc, imageWidth, imageHeight); - if (gc->foreground == defaultFg) { - [image setTemplate:YES]; - } + [image setTemplate:YES]; } [menuItem setImage:image]; if ((!image || mePtr->compound != COMPOUND_NONE) && mePtr->labelPtr && mePtr->labelLength) { title = [[[NSString alloc] initWithBytes:Tcl_GetString(mePtr->labelPtr) @@ -728,29 +747,54 @@ title = [NSString stringWithFormat:@"%@%C", [title substringToIndex:[title length] - 3], 0x2026]; } } [menuItem setTitle:title]; - if (strcmp(Tcl_GetString(fontPtr), "menu") || gc->foreground != defaultFg - || gc->background != defaultBg) { - attributes = TkMacOSXNSFontAttributesForFont(Tk_GetFontFromObj( - mePtr->menuPtr->tkwin, fontPtr)); - if (gc->foreground != defaultFg || gc->background != defaultBg) { - NSColor *color = TkMacOSXGetNSColor(gc, - gc->foreground!=defaultFg? gc->foreground:gc->background); - - attributes = [[attributes mutableCopy] autorelease]; - [(NSMutableDictionary *) attributes setObject:color - forKey:NSForegroundColorAttributeName]; - } - if (attributes) { - attributedTitle = [[[NSAttributedString alloc] - initWithString:title attributes:attributes] autorelease]; - } - } + +#if 0 + + /* + * The -background and -foreground options are now ignored in Aqua. + * See ticket [635167af14]. + */ + + NSDictionary fontAttributes = TkMacOSXNSFontAttributesForFont( + Tk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr)); + NSMutableDictionary *attributes = [fontAttributes mutableCopy]; + static unsigned long defaultBg = 0, defaultFg = 0; + if (defaultBg == 0) { + tkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_BG_COLOR); + defaultBg = tkColPtr->color.pixel; + ckfree(tkColPtr); + } + if (defaultFg == 0) { + tkColor *tkColPtr = TkpGetColor(NULL, DEF_MENU_FG); + defaultFg = tkColPtr->color.pixel; + ckfree(tkColPtr); + } + if (gc->foreground != defaultFg) { + NSColor *fgcolor = TkMacOSXGetNSColor(gc, gc->foreground); + [attributes setObject:fgcolor + forKey:NSForegroundColorAttributeName]; + } + if (gc->background != defaultBg) { + NSColor *bgcolor = TkMacOSXGetNSColor(gc, gc->background); + [attributes setObject:bgcolor + forKey:NSBackgroundColorAttributeName]; + } + +#else + + NSDictionary *attributes = TkMacOSXNSFontAttributesForFont( + Tk_GetFontFromObj(mePtr->menuPtr->tkwin, fontPtr)); + +#endif + + attributedTitle = [[NSAttributedString alloc] initWithString:title + attributes:attributes]; [menuItem setAttributedTitle:attributedTitle]; - [menuItem setEnabled:!(mePtr->state == ENTRY_DISABLED)]; + [menuItem setEnabled:(mePtr->state != ENTRY_DISABLED)]; [menuItem setState:((mePtr->type == CHECK_BUTTON_ENTRY || mePtr->type == RADIO_BUTTON_ENTRY) && mePtr->indicatorOn && (mePtr->entryFlags & ENTRY_SELECTED) ? NSOnState : NSOffState)]; if (mePtr->type != CASCADE_ENTRY && mePtr->accelPtr && mePtr->accelLength) { keyEquivalent = ParseAccelerator(Tcl_GetString(mePtr->accelPtr), @@ -779,31 +823,21 @@ [submenu setTitle:title]; if ([menuItem isEnabled]) { /* - * This menuItem might have been previously disabled (XXX: - * track this), which would have disabled entries; we must - * re-enable the entries here. - */ - - int i = 0; - NSArray *itemArray = [submenu itemArray]; - - for (NSMenuItem *item in itemArray) { - TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; - - /* - * Work around an apparent bug where itemArray can have - * more items than the menu's entries[] array. - */ - - if (i >= (int) menuRefPtr->menuPtr->numEntries) { - break; - } - [item setEnabled: !(submePtr->state == ENTRY_DISABLED)]; - i++; + * This menuItem might have been previously disabled which + * would have disabled all of its entries; we must re-enable the + * entries here. It is important to iterate though the Tk + * entries, not the NSMenuItems, since some NSMenuItems may + * have been added by the system. See [7185d26cf4]. + */ + + for (TkSizeT i = 0; i < menuRefPtr->menuPtr->numEntries; i++) { + TkMenuEntry *submePtr = menuRefPtr->menuPtr->entries[i]; + NSMenuItem *item = (NSMenuItem *) submePtr->platformEntryData; + [item setEnabled:(submePtr->state != ENTRY_DISABLED)]; } } } } } @@ -1672,12 +1706,10 @@ */ void TkpMenuInit(void) { - // TkColor *tkColPtr; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; #define observe(n, s) \ [nc addObserver:NSApp selector:@selector(s) name:(n) object:nil] observe(NSMenuDidBeginTrackingNotification, menuBeginTracking:); @@ -1813,17 +1845,21 @@ *---------------------------------------------------------------------- * * TkpDrawMenuEntry -- * * Draws the given menu entry at the given coordinates with the given - * attributes. + * attributes. This is a no-op on macOS since the menus are drawn by + * the Apple window manager, which also handles all events related to + * selecting menu items. This function is only called for tearoff + * menus, which are not supported on macOS but do get drawn as nearly + * invisible 1 pixel wide windows on macOS * * Results: * None. * * Side effects: - * X Server commands are executed to display the menu entry. + * None * *---------------------------------------------------------------------- */ void Index: macosx/tkMacOSXMenubutton.c ================================================================== --- macosx/tkMacOSXMenubutton.c +++ macosx/tkMacOSXMenubutton.c @@ -2,15 +2,15 @@ * tkMacOSXMenubutton.c -- * * This file implements the Macintosh specific portion of the menubutton * widget. * - * Copyright (c) 1996 by Sun Microsystems, Inc. - * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2006-2007 Daniel A. Steffen - * Copyright 2007 Revar Desmera. - * Copyright 2015 Kevin Walzer/WordTech Communications LLC. + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 2001 Apple Computer, Inc. + * Copyright © 2006-2007 Daniel A. Steffen + * Copyright © 2007 Revar Desmera. + * Copyright © 2015 Kevin Walzer/WordTech Communications LLC. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * */ @@ -163,12 +163,12 @@ void TkpDisplayMenuButton( ClientData clientData) /* Information about widget. */ { - MacMenuButton *mbPtr = clientData; - TkMenuButton *butPtr = clientData; + MacMenuButton *mbPtr = (MacMenuButton *)clientData; + TkMenuButton *butPtr = (TkMenuButton *)clientData; Tk_Window tkwin = butPtr->tkwin; Pixmap pixmap; DrawParams *dpPtr = &mbPtr->drawParams; butPtr->flags &= ~REDRAW_PENDING; @@ -238,12 +238,12 @@ * *---------------------------------------------------------------------- */ void -TkpComputeMenuButtonGeometry(butPtr) - TkMenuButton *butPtr; /* Widget record for menu button. */ +TkpComputeMenuButtonGeometry( + TkMenuButton *butPtr) /* Widget record for menu button. */ { int width, height, avgWidth, haveImage = 0, haveText = 0; int txtWidth, txtHeight; Tk_FontMetrics fm; int highlightWidth = butPtr->highlightWidth > 0 ? butPtr->highlightWidth : 0; @@ -687,12 +687,12 @@ static void MenuButtonEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkMenuButton *buttonPtr = clientData; - MacMenuButton *mbPtr = clientData; + TkMenuButton *buttonPtr = (TkMenuButton *)clientData; + MacMenuButton *mbPtr = (MacMenuButton *)clientData; if (eventPtr->type == ActivateNotify || eventPtr->type == DeactivateNotify) { if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { return; Index: macosx/tkMacOSXMenus.c ================================================================== --- macosx/tkMacOSXMenus.c +++ macosx/tkMacOSXMenus.c @@ -1,13 +1,13 @@ /* * tkMacOSXMenus.c -- * * These calls set up the default menus for Tk. * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 1995-1996 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -201,11 +201,11 @@ { (void)sender; if (!_eventInterp || !Tcl_FindCommand(_eventInterp, "tkAboutDialog", NULL, 0) || (GetCurrentEventKeyModifiers() & optionKey)) { - TkAboutDlg(); + [super orderFrontStandardAboutPanel:nil]; } else { int code = Tcl_EvalEx(_eventInterp, "tkAboutDialog", -1, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Index: macosx/tkMacOSXMouseEvent.c ================================================================== --- macosx/tkMacOSXMouseEvent.c +++ macosx/tkMacOSXMouseEvent.c @@ -2,12 +2,12 @@ * tkMacOSXMouseEvent.c -- * * This file implements functions that decode & handle mouse events on * MacOS X. * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -23,10 +23,17 @@ Window window; Point global; Point local; } MouseEventData; +typedef struct { + uint64_t wheelTickPrev; /* For high resolution wheels. */ + double vWheelAcc; /* For high resolution wheels (vertical). */ + double hWheelAcc; /* For high resolution wheels (horizontal). */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + static Tk_Window captureWinPtr = NULL; /* Current capture window; may be * NULL. */ static int GenerateButtonEvent(MouseEventData *medPtr); static unsigned int ButtonModifiers2State(UInt32 buttonState, @@ -115,10 +122,21 @@ [(TKWindow *)eventWindow setMouseInResizeArea:NO]; break; } case NSLeftMouseUp: case NSLeftMouseDown: + + /* + * Ignore mouse button events which arrive while the app is inactive. + * These events will be resent after activation, causing duplicate + * actions when an app is activated by a bound mouse event. See ticket + * [7bda9882cb]. + */ + + if (! [NSApp isActive]) { + return theEvent; + } case NSMouseMoved: case NSScrollWheel: #if 0 case NSCursorUpdate: case NSTabletPoint: @@ -307,10 +325,12 @@ Tk_UpdatePointer(target, global.x, global.y, state); } else { CGFloat delta; XEvent xEvent; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * For scroll wheel events we need to send the XEvent here. */ @@ -321,23 +341,47 @@ xEvent.xbutton.y_root = global.y; xEvent.xany.send_event = false; xEvent.xany.display = Tk_Display(target); xEvent.xany.window = Tk_WindowId(target); - delta = [theEvent deltaY] * 120; - if (delta != 0.0) { - xEvent.xbutton.state = state; - xEvent.xkey.keycode = (delta > 0) ? ceil(delta) : floor(delta); - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); - } - delta = [theEvent deltaX] * 120; - if (delta != 0.0) { - xEvent.xbutton.state = state | ShiftMask; - xEvent.xkey.keycode = (delta > 0) ? ceil(delta) : floor(delta); - xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); - Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); +#define WHEEL_DELTA 120 +#define WHEEL_DELAY 300000000 + uint64_t wheelTick = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW); + Bool timeout = (wheelTick - tsdPtr->wheelTickPrev) >= WHEEL_DELAY; + if (timeout) { + tsdPtr->vWheelAcc = tsdPtr->hWheelAcc = 0; + } + tsdPtr->wheelTickPrev = wheelTick; + delta = [theEvent deltaY]; + if (delta != 0.0) { + delta = (tsdPtr->vWheelAcc += delta); + if (timeout && fabs(delta) < 1.0) { + delta = ((delta < 0.0) ? -1.0 : 1.0); + } + if (fabs(delta) >= 0.6) { + int intDelta = round(delta); + xEvent.xbutton.state = state; + xEvent.xkey.keycode = WHEEL_DELTA * intDelta; + tsdPtr->vWheelAcc -= intDelta; + xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + } + } + delta = [theEvent deltaX]; + if (delta != 0.0) { + delta = (tsdPtr->hWheelAcc += delta); + if (timeout && fabs(delta) < 1.0) { + delta = ((delta < 0.0) ? -1.0 : 1.0); + } + if (fabs(delta) >= 0.6) { + int intDelta = round(delta); + xEvent.xbutton.state = state | ShiftMask; + xEvent.xkey.keycode = WHEEL_DELTA * intDelta; + tsdPtr->hWheelAcc -= intDelta; + xEvent.xany.serial = LastKnownRequestProcessed(Tk_Display(tkwin)); + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + } } } return theEvent; } @end @@ -684,10 +728,16 @@ pt.x = dispPtr->warpX; pt.y = dispPtr->warpY; } CGWarpMouseCursorPosition(pt); + + if (dispPtr->warpWindow) { + TkGenerateButtonEventForXPointer(Tk_WindowId(dispPtr->warpWindow)); + } else { + TkGenerateButtonEventForXPointer(None); + } } /* *---------------------------------------------------------------------- * Index: macosx/tkMacOSXNotify.c ================================================================== --- macosx/tkMacOSXNotify.c +++ macosx/tkMacOSXNotify.c @@ -2,32 +2,59 @@ * tkMacOSXNotify.c -- * * This file contains the implementation of a tcl event source * for the AppKit event loop. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright 2015 Marc Culler. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2015 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#include #include "tkMacOSXPrivate.h" #include "tkMacOSXInt.h" #include "tkMacOSXConstants.h" +#if TCL_MAJOR_VERSION < 9 +#undef Tcl_MacOSXNotifierAddRunLoopMode +#ifdef USE_TCL_STUBS +#ifdef __cplusplus +extern "C" { +#endif +/* Little hack to eliminate the need for "tclInt.h" here: + Just copy a small portion of TclIntPlatStubs, just + enough to make it work. See [600b72bfbc] */ +typedef struct TclIntPlatStubs { + int magic; + void *hooks; + void (*dummy[19]) (void); /* dummy entries 0-18, not used */ + void (*tclMacOSXNotifierAddRunLoopMode) (const void *runLoopMode); /* 19 */ +} TclIntPlatStubs; +extern const TclIntPlatStubs *tclIntPlatStubsPtr; +#ifdef __cplusplus +} +#endif +#define Tcl_MacOSXNotifierAddRunLoopMode \ + (tclIntPlatStubsPtr->tclMacOSXNotifierAddRunLoopMode) /* 19 */ +#elif TCL_MINOR_VERSION < 7 + extern void TclMacOSXNotifierAddRunLoopMode(const void *runLoopMode); +# define Tcl_MacOSXNotifierAddRunLoopMode TclMacOSXNotifierAddRunLoopMode +#else + extern void Tcl_MacOSXNotifierAddRunLoopMode(const void *runLoopMode); +#endif +#endif #import /* This is not used for anything at the moment. */ typedef struct ThreadSpecificData { int initialized; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -#define TSD_INIT() ThreadSpecificData *tsdPtr = \ +#define TSD_INIT() ThreadSpecificData *tsdPtr = (ThreadSpecificData *) \ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)) static void TkMacOSXNotifyExitHandler(ClientData clientData); static void TkMacOSXEventsSetupProc(ClientData clientData, int flags); static void TkMacOSXEventsCheckProc(ClientData clientData, int flags); @@ -267,12 +294,12 @@ "first [load] of TkAqua has to occur in the main thread!"); } Tcl_CreateEventSource(TkMacOSXEventsSetupProc, TkMacOSXEventsCheckProc, NULL); TkCreateExitHandler(TkMacOSXNotifyExitHandler, NULL); - TclMacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode); - TclMacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode); + Tcl_MacOSXNotifierAddRunLoopMode(NSEventTrackingRunLoopMode); + Tcl_MacOSXNotifierAddRunLoopMode(NSModalPanelRunLoopMode); } } } /* @@ -314,12 +341,13 @@ * This relies on a feature of [NSApp nextEventMatchingMask: ...] which * is undocumented, namely that it sometimes blocks and calls drawRect * for all views that need display before it returns. We call it with * deQueue=NO so that it will not change anything on the AppKit event * queue, because we only want the side effect that it runs drawRect. The - * only time when any NSViews have the needsDisplay property set to YES - * is during execution of this function. + * only times when any NSViews have the needsDisplay property set to YES + * are during execution of this function or in the addDirtyRect method + * of TKContentView. * * The reason for running this function as an idle task is to try to * arrange that all widgets will be fully configured before they are * drawn. Any idle tasks that might reconfigure them should be higher on * the idle queue, so they should be run before the display procs are run @@ -332,11 +360,11 @@ * * Results: * None. * * Side effects: - * Parts of windows my get redrawn. + * Parts of windows may get redrawn. * *---------------------------------------------------------------------- */ void @@ -351,11 +379,12 @@ if ([view tkNeedsDisplay]) { count++; if (dirtyCount) { continue; } - [view setNeedsDisplayInRect:[view tkDirtyRect]]; + [[view layer] setNeedsDisplayInRect:[view tkDirtyRect]]; + [view setNeedsDisplay:YES]; } } else { [window displayIfNeeded]; } } @@ -443,11 +472,11 @@ * Tcl_WaitForEvent. Then it will call check proc to collect the * events and translate them into XEvents. * * If we have any events waiting or if there is any drawing to be done * we want Tcl_WaitForEvent to return immediately. So we set the block - * time to 0 and stop the heatbeat. + * time to 0 and stop the heartbeat. */ NSEvent *currentEvent = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] Index: macosx/tkMacOSXPort.h ================================================================== --- macosx/tkMacOSXPort.h +++ macosx/tkMacOSXPort.h @@ -33,20 +33,14 @@ #endif #include #ifndef _TCL # include #endif -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H +#if HAVE_SYS_TIME_H # include -# else -# include -# endif #endif +#include #if HAVE_INTTYPES_H # include #endif #include #if defined(__GNUC__) && !defined(__cplusplus) @@ -75,10 +69,23 @@ # else # define SELECT_MASK int # endif #endif +/* + * Used to tag functions that are only to be visible within the module being + * built and not outside it (where this is supported by the linker). + */ + +#ifndef MODULE_SCOPE +# ifdef __cplusplus +# define MODULE_SCOPE extern "C" +# else +# define MODULE_SCOPE extern +# endif +#endif + /* * The following macro defines the number of fd_masks in an fd_set: */ #ifndef FD_SETSIZE @@ -133,15 +140,26 @@ #define TK_NO_DOUBLE_BUFFERING 1 #define TK_HAS_DYNAMIC_COLORS 1 #define TK_DYNAMIC_COLORMAP 0x0fffffff /* - * Inform tkImgPhInstance.c that our tkPutImage can render an image with an - * alpha channel directly into a window. + * Inform tkImgPhInstance.c that we implement TkpPutRGBAImage to render RGBA + * images directly into a window. + */ + +#define TK_CAN_RENDER_RGBA + +MODULE_SCOPE int TkpPutRGBAImage( + Display* display, Drawable drawable, GC gc,XImage* image, + int src_x, int src_y, int dest_x, int dest_y, + unsigned int width, unsigned int height); + +/* + * Inform tkCanvas.c that our XGetImage returns a 32pp pixmap packed as 0xAABBGGRR */ -#define TKPUTIMAGE_CAN_BLEND +#define TK_XGETIMAGE_USES_ABGR32 /* * Used by xcolor.c */ ADDED macosx/tkMacOSXPrint.c Index: macosx/tkMacOSXPrint.c ================================================================== --- /dev/null +++ macosx/tkMacOSXPrint.c @@ -0,0 +1,353 @@ +/* + * tkMacOSXPrint.c -- + * + * This module implements native printing dialogs for macOS. + * + * Copyright © 2006 Apple Inc. + * Copyright © 2011-2021 Kevin Walzer/WordTech Communications LLC. + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Forward declarations of functions and variables. */ +NSString * fileName = nil; +CFStringRef urlFile = NULL; +int StartPrint(ClientData clientData, Tcl_Interp * interp, + int objc, Tcl_Obj * const objv[]); +OSStatus FinishPrint(NSString *file, int buttonValue); +int MacPrint_Init(Tcl_Interp * interp); + +/* Delegate class for print dialogs. */ +@interface PrintDelegate: NSObject + - (id) init; + - (void) printPanelDidEnd: (NSPrintPanel *) printPanel + returnCode: (int) returnCode + contextInfo: (void *) contextInfo; +@end + +@implementation PrintDelegate +- (id) init { + self = [super init]; + return self; +} + +- (void) printPanelDidEnd: (NSPrintPanel *) printPanel + returnCode: (int) returnCode + contextInfo: (void *) contextInfo { + /* + * Pass returnCode to FinishPrint function to determine how to + * handle. + */ + FinishPrint(fileName, returnCode); +} +@end + +/* + *---------------------------------------------------------------------- + * + * StartPrint -- + * + * Launch native print dialog. + * + * Results: + * Configures values and starts print process. + * + *---------------------------------------------------------------------- + */ + +int +StartPrint( + ClientData clientData, + Tcl_Interp * interp, + int objc, + Tcl_Obj *const objv[]) +{ + (void) clientData; + NSPrintInfo * printInfo = [NSPrintInfo sharedPrintInfo]; + NSPrintPanel * printPanel = [NSPrintPanel printPanel]; + int accepted; + PMPrintSession printSession; + PMPageFormat pageFormat; + PMPrintSettings printSettings; + OSStatus status = noErr; + + /* Check for proper number of arguments. */ + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "file"); + return TCL_ERROR; + } + + fileName = [NSString stringWithUTF8String: Tcl_GetString(objv[1])]; + urlFile = (CFStringRef) fileName; + CFRetain(urlFile); + + /* Initialize the delegate for the callback from the page panel. */ + PrintDelegate * printDelegate = [[PrintDelegate alloc] init]; + + status = PMCreateSession( & printSession); + if (status != noErr) { + NSLog(@ "Error creating print session."); + return TCL_ERROR; + } + + status = PMCreatePrintSettings( & printSettings); + if (status != noErr) { + NSLog(@ "Error creating print settings."); + return TCL_ERROR; + } + + status = PMSessionDefaultPrintSettings(printSession, printSettings); + if (status != noErr) { + NSLog(@ "Error creating default print settings."); + return TCL_ERROR; + } + + printSession = (PMPrintSession)[printInfo PMPrintSession]; + pageFormat = (PMPageFormat)[printInfo PMPageFormat]; + printSettings = (PMPrintSettings)[printInfo PMPrintSettings]; + + accepted = [printPanel runModalWithPrintInfo: printInfo]; + [printDelegate printPanelDidEnd: printPanel + returnCode: accepted + contextInfo: printInfo]; + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * FinishPrint -- + * + * Handles print process based on input from dialog. + * + * Results: + * Completes print process. + * + *---------------------------------------------------------------------- + */ + +OSStatus +FinishPrint( + NSString *file, + int buttonValue) +{ + NSPrintInfo * printInfo = [NSPrintInfo sharedPrintInfo]; + PMPrintSession printSession; + PMPageFormat pageFormat; + PMPrintSettings printSettings; + OSStatus status = noErr; + CFStringRef mimeType = NULL; + + /* + * If value passed here is NSCancelButton, return noErr; + * otherwise printing will occur regardless of value. + */ + if (buttonValue == NSModalResponseCancel) { + return noErr; + } + + status = PMCreateSession( & printSession); + if (status != noErr) { + NSLog(@ "Error creating print session."); + return status; + } + + status = PMCreatePrintSettings( & printSettings); + if (status != noErr) { + NSLog(@ "Error creating print settings."); + return status; + } + + status = PMSessionDefaultPrintSettings(printSession, printSettings); + if (status != noErr) { + NSLog(@ "Error creating default print settings."); + return status; + } + + printSession = (PMPrintSession)[printInfo PMPrintSession]; + pageFormat = (PMPageFormat)[printInfo PMPageFormat]; + printSettings = (PMPrintSettings)[printInfo PMPrintSettings]; + + /*Handle print operation.*/ + if (buttonValue == NSModalResponseOK) { + + if (urlFile == NULL) { + NSLog(@ "Could not get file to print."); + return noErr; + } + + fileName = file; + + CFURLRef printURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, urlFile, kCFURLPOSIXPathStyle, false); + + PMPrinter currentPrinter; + PMDestinationType printDestination; + + /*Get the intended destination.*/ + status = PMSessionGetDestinationType(printSession, printSettings, & printDestination); + + /*Destination is printer. Send file to printer.*/ + if (status == noErr && printDestination == kPMDestinationPrinter) { + + status = PMSessionGetCurrentPrinter(printSession, & currentPrinter); + if (status == noErr) { + CFArrayRef mimeTypes; + status = PMPrinterGetMimeTypes(currentPrinter, printSettings, & mimeTypes); + if (status == noErr && mimeTypes != NULL) { + mimeType = CFSTR("application/pdf"); + if (CFArrayContainsValue(mimeTypes, CFRangeMake(0, CFArrayGetCount(mimeTypes)), mimeType)) { + status = PMPrinterPrintWithFile(currentPrinter, printSettings, pageFormat, mimeType, printURL); + CFRelease(urlFile); + return status; + } + } + } + } + + /* Destination is file. Determine how to handle. */ + if (status == noErr && printDestination == kPMDestinationFile) { + CFURLRef outputLocation = NULL; + + status = PMSessionCopyDestinationLocation(printSession, printSettings, & outputLocation); + if (status == noErr) { + /*Get the source file and target destination, convert to strings.*/ + CFStringRef sourceFile = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); + CFStringRef savePath = CFURLCopyFileSystemPath(outputLocation, kCFURLPOSIXPathStyle); + NSString * sourcePath = (NSString * ) sourceFile; + NSString * finalPath = (NSString * ) savePath; + NSString * pathExtension = [finalPath pathExtension]; + NSFileManager * fileManager = [NSFileManager defaultManager]; + NSError * error = nil; + + /* + * Is the target file a PDF? If so, copy print file + * to output location. + */ + if ([pathExtension isEqualToString: @ "pdf"]) { + + /*Make sure no file conflict exists.*/ + if ([fileManager fileExistsAtPath: finalPath]) { + [fileManager removeItemAtPath: finalPath error: &error]; + } + if ([fileManager fileExistsAtPath: sourcePath]) { + error = nil; + [fileManager copyItemAtPath: sourcePath toPath: finalPath error: & error]; + } + return status; + } + + /* + * Is the target file PostScript? If so, run print file + * through CUPS filter to convert back to PostScript. + */ + + if ([pathExtension isEqualToString: @ "ps"]) { + char source[5012]; + char target[5012]; + [sourcePath getCString: source maxLength: (sizeof source) encoding: NSUTF8StringEncoding]; + [finalPath getCString: target maxLength: (sizeof target) encoding: NSUTF8StringEncoding]; + /*Make sure no file conflict exists.*/ + if ([fileManager fileExistsAtPath: finalPath]) { + [fileManager removeItemAtPath: finalPath error: &error]; + } + + /* + * Fork and start new process with command string. Thanks to Peter da Silva + * for assistance. + */ + pid_t pid; + if ((pid = fork()) == -1) { + return -1; + } else if (pid == 0) { + /* Redirect output to file and silence debugging output.*/ + dup2(open(target, O_RDWR | O_CREAT, 0777), 1); + dup2(open("/dev/null", O_WRONLY), 2); + execl("/usr/sbin/cupsfilter", "/usr/sbin/cupsfilter", "-m", "application/postscript", source, NULL); + exit(0); + } + return status; + } + } + } + + /* Destination is preview. Open file in default application for PDF. */ + if ((status == noErr) && (printDestination == kPMDestinationPreview)) { + CFStringRef urlpath = CFURLCopyFileSystemPath(printURL, kCFURLPOSIXPathStyle); + NSString * path = (NSString * ) urlpath; + NSURL * url = [NSURL fileURLWithPath: path]; + NSWorkspace * ws = [NSWorkspace sharedWorkspace]; + [ws openURL: url]; + status = noErr; + return status; + } + + /* + * If destination is not printer, file or preview, + * we do not support it. Display alert. + */ + + if (((status == noErr) && (printDestination != kPMDestinationPreview)) || ((status == noErr) && (printDestination != kPMDestinationFile)) || ((status == noErr) && (printDestination != kPMDestinationPrinter))) { + + NSAlert * alert = [[[NSAlert alloc] init] autorelease]; + [alert addButtonWithTitle: @ "OK"]; + + [alert setMessageText: @ "Unsupported Printing Operation"]; + [alert setInformativeText: @ "This printing operation is not supported."]; + [alert setAlertStyle: NSAlertStyleInformational]; + [alert runModal]; + return status; + } + } + + /* Return because cancel button was clicked. */ + if (buttonValue == NSModalResponseCancel) { + PMRelease(printSession); + return status; + } + + return status; +} + +/* + *---------------------------------------------------------------------- + * + * MacPrint_Init-- + * + * Initializes the printing module. + * + * Results: + * Printing module initialized. + * + *---------------------------------------------------------------------- + */ + +int MacPrint_Init(Tcl_Interp * interp) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + Tcl_CreateObjCommand(interp, "::tk::print::_print", StartPrint, (ClientData) NULL, (Tcl_CmdDeleteProc * ) NULL); + [pool release]; + return TCL_OK; +} + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ Index: macosx/tkMacOSXPrivate.h ================================================================== --- macosx/tkMacOSXPrivate.h +++ macosx/tkMacOSXPrivate.h @@ -1,13 +1,13 @@ /* * tkMacOSXPrivate.h -- * * Macros and declarations that are purely internal & private to TkAqua. * - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2008-2009 Apple Inc. - * Copyright (c) 2020 Marc Culler + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2008-2009 Apple Inc. + * Copyright © 2020 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id$ @@ -23,12 +23,15 @@ #ifndef __clang__ #define instancetype id #endif #define TextStyle MacTextStyle +#define Cursor QDCursor #import +#undef Cursor #import +#import #ifndef NO_CARBON_H #import #endif #undef TextStyle #import /* for sel_isEqual() */ @@ -134,11 +137,11 @@ */ typedef struct keycode_v_t { unsigned keychar: 22; /* UCS-32 character */ unsigned o_s: 2; /* State of Option and Shift keys. */ - unsigned virtual: 8; /* 8-bit virtual keycode - identifies a key. */ + unsigned virt: 8; /* 8-bit virtual keycode - identifies a key. */ } keycode_v; typedef struct keycode_x_t { unsigned keychar: 22; /* UCS-32 character */ unsigned xvirtual: 10; /* Combines o_s and virtual. This 10-bit integer @@ -156,11 +159,11 @@ /* * Macros used in tkMacOSXKeyboard.c and tkMacOSXKeyEvent.c. * Note that 0x7f is del and 0xF8FF is the Apple Logo character. */ -#define ON_KEYPAD(virtual) ((virtual >= 0x41) && (virtual <= 0x5C)) +#define ON_KEYPAD(virt) ((virt >= 0x41) && (virt <= 0x5C)) #define IS_PRINTABLE(keychar) ((keychar >= 0x20) && (keychar != 0x7f) && \ ((keychar < 0xF700) || keychar >= 0xF8FF)) /* * An "index" is 2-bit bitfield showing the state of the Option and Shift @@ -202,11 +205,10 @@ typedef struct TkMacOSXDrawingContext { CGContextRef context; NSView *view; HIShapeRef clipRgn; - CGRect portBounds; } TkMacOSXDrawingContext; /* * Variables internal to TkAqua. */ @@ -230,11 +232,12 @@ HIMutableShapeRef inShape, const CGRect *inRect); MODULE_SCOPE OSStatus TkMacOSHIShapeUnionWithRect(HIMutableShapeRef inShape, const CGRect *inRect); MODULE_SCOPE OSStatus TkMacOSHIShapeUnion(HIShapeRef inShape1, HIShapeRef inShape2, HIMutableShapeRef outResult); - +MODULE_SCOPE int TkMacOSXCountRectsInRegion(HIShapeRef shape); +MODULE_SCOPE void TkMacOSXPrintRectsInRegion(HIShapeRef shape); /* * Prototypes of TkAqua internal procs. */ MODULE_SCOPE void * TkMacOSXGetNamedSymbol(const char *module, @@ -268,11 +271,10 @@ HIShapeRef rgn); MODULE_SCOPE NSImage* TkMacOSXGetNSImageFromTkImage(Display *display, Tk_Image image, int width, int height); MODULE_SCOPE NSImage* TkMacOSXGetNSImageFromBitmap(Display *display, Pixmap bitmap, GC gc, int width, int height); -MODULE_SCOPE CGColorRef TkMacOSXCreateCGColor(GC gc, unsigned long pixel); MODULE_SCOPE NSColor* TkMacOSXGetNSColor(GC gc, unsigned long pixel); MODULE_SCOPE NSFont* TkMacOSXNSFontForFont(Tk_Font tkfont); MODULE_SCOPE NSDictionary* TkMacOSXNSFontAttributesForFont(Tk_Font tkfont); MODULE_SCOPE NSModalSession TkMacOSXGetModalSession(void); MODULE_SCOPE void TkMacOSXSelDeadWindow(TkWindow *winPtr); @@ -293,10 +295,13 @@ MODULE_SCOPE void TkMacOSXWinNSBounds(TkWindow *winPtr, NSView *view, NSRect *bounds); MODULE_SCOPE Bool TkMacOSXInDarkMode(Tk_Window tkwin); MODULE_SCOPE void TkMacOSXDrawAllViews(ClientData clientData); MODULE_SCOPE unsigned long TkMacOSXClearPixel(void); +MODULE_SCOPE int MacSystrayInit(Tcl_Interp *); +MODULE_SCOPE int MacPrint_Init(Tcl_Interp *); + #pragma mark Private Objective-C Classes #define VISIBILITY_HIDDEN __attribute__((visibility("hidden"))) @@ -331,17 +336,19 @@ /* The Objective C runtime used on i386 requires this. */ int _poolLock; int _macOSVersion; /* 10000 * major + 100*minor */ Bool _isDrawing; Bool _needsToDraw; + Bool _isSigned; #endif } @property int poolLock; @property int macOSVersion; @property Bool isDrawing; @property Bool needsToDraw; +@property Bool isSigned; @end @interface TKApplication(TKInit) - (NSString *)tkFrameworkImagePath:(NSString*)image; - (void)_resetAutoreleasePool; @@ -557,10 +564,11 @@ @interface TKNSString:NSString { @private Tcl_DString _ds; NSString *_string; + const char *_UTF8String; } @property const char *UTF8String; @property (readonly) Tcl_DString DString; - (instancetype)initWithTclUtfBytes:(const void *)bytes length:(NSUInteger)len; Index: macosx/tkMacOSXRegion.c ================================================================== --- macosx/tkMacOSXRegion.c +++ macosx/tkMacOSXRegion.c @@ -1,13 +1,13 @@ /* * tkMacOSXRegion.c -- * * Implements X window calls for manipulating regions * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1995-1996 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -553,13 +553,62 @@ result = HIShapeUnion(inShape1, inShape2, outResult); return result; } +static OSStatus +rectCounter( + TCL_UNUSED(int), + TCL_UNUSED(HIShapeRef), + TCL_UNUSED(const CGRect *), + void *ref) +{ + int *count = (int *)ref; + (*count)++; + return noErr; +} + +static OSStatus +rectPrinter( + TCL_UNUSED(int), + TCL_UNUSED(HIShapeRef), + const CGRect *rect, + TCL_UNUSED(void *)) +{ + if (rect) { + fprintf(stderr, " %s\n", NSStringFromRect(*rect).UTF8String); + } + return noErr; +} + +int +TkMacOSXCountRectsInRegion( + HIShapeRef shape) +{ + int rect_count = 0; + if (!HIShapeIsEmpty(shape)) { + ChkErr(HIShapeEnumerate, shape, + kHIShapeParseFromBottom|kHIShapeParseFromLeft, + rectCounter, &rect_count); + } + return rect_count; +} + +void +TkMacOSXPrintRectsInRegion( + HIShapeRef shape) +{ + if (!HIShapeIsEmpty(shape)) { + ChkErr(HIShapeEnumerate, shape, + kHIShapeParseFromBottom|kHIShapeParseFromLeft, + rectPrinter, NULL); + } +} + /* * Local Variables: * mode: objc * c-basic-offset: 4 * fill-column: 79 * coding: utf-8 * End: */ Index: macosx/tkMacOSXScale.c ================================================================== --- macosx/tkMacOSXScale.c +++ macosx/tkMacOSXScale.c @@ -2,14 +2,14 @@ * tkMacOSXScale.c -- * * This file implements the Macintosh specific portion of the * scale widget. * - * Copyright (c) 1996 by Sun Microsystems, Inc. - * Copyright (c) 1998-2000 by Scriptics Corporation. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright 2008-2009, Apple Inc. + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 1998-2000 Scriptics Corporation. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2008-2009 Apple Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXScrlbr.c ================================================================== --- macosx/tkMacOSXScrlbr.c +++ macosx/tkMacOSXScrlbr.c @@ -2,15 +2,15 @@ * tkMacOSXScrollbar.c -- * * This file implements the Macintosh specific portion of the scrollbar * widget. * - * Copyright (c) 1996 by Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2015 Kevin Walzer/WordTech Commununications LLC. - * Copyright (c) 2018-2019 Marc Culler + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2015 Kevin Walzer/WordTech Commununications LLC. + * Copyright © 2018-2019 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -244,11 +244,11 @@ void TkpDisplayScrollbar( ClientData clientData) /* Information about window. */ { - TkScrollbar *scrollPtr = clientData; + TkScrollbar *scrollPtr = (TkScrollbar *)clientData; MacScrollbar *msPtr = (MacScrollbar *) scrollPtr; Tk_Window tkwin = scrollPtr->tkwin; TkWindow *winPtr = (TkWindow *) tkwin; TkMacOSXDrawingContext dc; @@ -454,14 +454,14 @@ TkpDestroyScrollbar( TkScrollbar *scrollPtr) { MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; - if (macScrollPtr->troughGC != None) { + if (macScrollPtr->troughGC != NULL) { Tk_FreeGC(scrollPtr->display, macScrollPtr->troughGC); } - if (macScrollPtr->copyGC != None) { + if (macScrollPtr->copyGC != NULL) { Tk_FreeGC(scrollPtr->display, macScrollPtr->copyGC); } } /* @@ -768,11 +768,11 @@ static void ScrollbarEventProc( ClientData clientData, /* Information about window. */ XEvent *eventPtr) /* Information about event. */ { - TkScrollbar *scrollPtr = clientData; + TkScrollbar *scrollPtr = (TkScrollbar *)clientData; switch (eventPtr->type) { case UnmapNotify: TkMacOSXSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false); break; @@ -782,14 +782,14 @@ break; case ButtonPress: case ButtonRelease: case EnterNotify: case LeaveNotify: - ScrollbarEvent(clientData, eventPtr); + ScrollbarEvent(scrollPtr, eventPtr); break; default: - TkScrollbarEventProc(clientData, eventPtr); + TkScrollbarEventProc(scrollPtr, eventPtr); } } /* * Local Variables: Index: macosx/tkMacOSXSend.c ================================================================== --- macosx/tkMacOSXSend.c +++ macosx/tkMacOSXSend.c @@ -20,14 +20,14 @@ * Implementing this has been on our list of things to do, but what with * the demise of Tcl at Sun, and the lack of resources at Scriptics it * may not get done for awhile. So this sketch is offered for the brave * to attempt if they need the functionality... * - * Copyright (c) 1989-1994 The Regents of the University of California. - * Copyright (c) 1994-1998 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 1989-1994 The Regents of the University of California. + * Copyright © 1994-1998 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXServices.c ================================================================== --- macosx/tkMacOSXServices.c +++ macosx/tkMacOSXServices.c @@ -1,13 +1,13 @@ /* * tkMacOSXServices.c -- *\ * This file allows the integration of Tk and the Cocoa NSServices API. * - * Copyright (c) 2010-2019 Kevin Walzer/WordTech Communications LLC. - * Copyright (c) 2019 Marc Culler. - * Copyright (c) 2010 Adrian Robert. + * Copyright © 2010-2019 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2019 Marc Culler. + * Copyright © 2010 Adrian Robert. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXSubwindows.c ================================================================== --- macosx/tkMacOSXSubwindows.c +++ macosx/tkMacOSXSubwindows.c @@ -1,13 +1,13 @@ /* * tkMacOSXSubwindows.c -- * * Implements subwindows for the macintosh version of Tk. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -103,11 +103,11 @@ macWin->drawRgn = NULL; } macWin->view = nil; /* - * Delay deletion of a toplevel data structure untill all children have + * Delay deletion of a toplevel data structure until all children have * been deleted. */ if (macWin->toplevel->referenceCount == 0) { ckfree(macWin->toplevel); @@ -971,11 +971,11 @@ TCL_UNUSED(HIShapeRef), const CGRect *rect, void *ref) { static CGAffineTransform t; - TKContentView *view = ref; + TKContentView *view = (TKContentView *)ref; NSRect dirtyRect; if (!view) { return paramErr; } @@ -1433,16 +1433,20 @@ { MacDrawable *macPix = (MacDrawable *)pixmap; display->request++; if (macPix->context) { - char *data = CGBitmapContextGetData(macPix->context); + char *data = (char *)CGBitmapContextGetData(macPix->context); if (data) { ckfree(data); } - CFRelease(macPix->context); + /* + * Releasing the context here causes a crash in the 8.7 regression + * tests, but not in 8.6. + * CFRelease(macPix->context); + */ } ckfree(macPix); } /* ADDED macosx/tkMacOSXSysTray.c Index: macosx/tkMacOSXSysTray.c ================================================================== --- /dev/null +++ macosx/tkMacOSXSysTray.c @@ -0,0 +1,497 @@ +/* + * tkMacOSXSysTray.c -- + * + * tkMacOSXSysTray.c implements a "systray" Tcl command which allows + * one to change the system tray/taskbar icon of a Tk toplevel + * window and a "sysnotify" command to post system notifications. + * In macOS the icon appears on the right hand side of the menu bar. + * + * Copyright © 2020 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2020 Jan Nijtmans. + * Copyright © 2020 Marc Culler. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include +#include +#include "tkMacOSXPrivate.h" + +/* + * Class declaration for TkStatusItem. + */ + +@interface TkStatusItem: NSObject { + NSStatusItem * statusItem; + NSStatusBar * statusBar; + NSImage * icon; + NSString * tooltip; + Tcl_Interp * interp; + Tcl_Obj * b1_callback; + Tcl_Obj * b3_callback; +} + +- (id) init : (Tcl_Interp *) interp; +- (void) setImagewithImage : (NSImage *) image; +- (void) setTextwithString : (NSString *) string; +- (void) setB1Callback : (Tcl_Obj *) callback; +- (void) setB3Callback : (Tcl_Obj *) callback; +- (void) clickOnStatusItem; +- (void) dealloc; + +@end + + + +/* + * Class declaration for TkStatusItem. A TkStatusItem represents an icon posted + * on the status bar located on the right side of the MenuBar. Each interpreter + * may have at most one TkStatusItem. A pointer to the TkStatusItem belonging + * to an interpreter is stored as the clientData of the MacSystrayObjCmd instance + * in that interpreter. It will be NULL until the tk systray command is executed + * by the interpreter. + */ + +@implementation TkStatusItem : NSObject + +- (id) init : (Tcl_Interp *) interpreter { + [super init]; + statusBar = [NSStatusBar systemStatusBar]; + statusItem = [[statusBar statusItemWithLength:NSVariableStatusItemLength] retain]; + statusItem.button.target = self; + statusItem.button.action = @selector(clickOnStatusItem); + [statusItem.button sendActionOn : NSEventMaskLeftMouseUp | NSEventMaskRightMouseUp]; + statusItem.visible = YES; + interp = interpreter; + b1_callback = NULL; + b3_callback = NULL; + return self; +} + +- (void) setImagewithImage : (NSImage *) image +{ + icon = nil; + icon = image; + statusItem.button.image = icon; +} + +- (void) setTextwithString : (NSString *) string +{ + tooltip = nil; + tooltip = string; + statusItem.button.toolTip = tooltip; +} + +- (void) setB1Callback : (Tcl_Obj *) obj +{ + if (obj != NULL) { + Tcl_IncrRefCount(obj); + } + if (b1_callback != NULL) { + Tcl_DecrRefCount(b1_callback); + } + b1_callback = obj; +} + +- (void) setB3Callback : (Tcl_Obj *) obj +{ + if (obj != NULL) { + Tcl_IncrRefCount(obj); + } + if (b3_callback != NULL) { + Tcl_DecrRefCount(b3_callback); + } + b3_callback = obj; +} + +- (void) clickOnStatusItem +{ + NSEvent *event = [NSApp currentEvent]; + if (([event type] == NSEventTypeLeftMouseUp) && (b1_callback != NULL)) { + int result = Tcl_EvalObjEx(interp, b1_callback, TCL_EVAL_GLOBAL); + if (result != TCL_OK) { + Tcl_BackgroundException(interp, result); + } + } else { + if (([event type] == NSEventTypeRightMouseUp) && (b3_callback != NULL)) { + int result = Tcl_EvalObjEx(interp, b3_callback, TCL_EVAL_GLOBAL); + if (result != TCL_OK) { + Tcl_BackgroundException(interp, result); + } + } + } +} +- (void) dealloc +{ + [statusBar removeStatusItem: statusItem]; + if (b1_callback != NULL) { + Tcl_DecrRefCount(b1_callback); + } + if (b3_callback != NULL) { + Tcl_DecrRefCount(b3_callback); + } + [super dealloc]; +} + +@end + +/* + * Type used for the ClientData of a MacSystrayObjCmd instance. + */ + +typedef TkStatusItem** StatusItemInfo; + + + +/* + *---------------------------------------------------------------------- + * + * MacSystrayDestroy -- + * + * Removes an intepreters icon from the status bar. + * + * Results: + * None. + * + * Side effects: + * The icon is removed and memory is freed. + * + *---------------------------------------------------------------------- + */ + +static void +MacSystrayDestroy( + ClientData clientData, + TCL_UNUSED(Tcl_Interp *)) +{ + StatusItemInfo info = (StatusItemInfo)clientData; + if (info) { + [*info release]; + ckfree(info); + } +} + +/* + *---------------------------------------------------------------------- + * + * MacSystrayObjCmd -- + * + * Main command for creating, displaying, and removing icons from the + * status bar. + * + * Results: + * + * A standard Tcl result. + * + * Side effects: + * + * Management of icon display in the status bar. + * + *---------------------------------------------------------------------- + */ + +static int +MacSystrayObjCmd( + void *clientData, + Tcl_Interp * interp, + int objc, + Tcl_Obj *const *objv) +{ + Tk_Image tk_image; + int result, idx; + static const char *options[] = + {"create", "modify", "destroy", NULL}; + typedef enum {TRAY_CREATE, TRAY_MODIFY, TRAY_DESTROY} optionsEnum; + static const char *modifyOptions[] = + {"image", "text", "b1_callback", "b3_callback", NULL}; + typedef enum {TRAY_IMAGE, TRAY_TEXT, TRAY_B1_CALLBACK, TRAY_B3_CALLBACK + } modifyOptionsEnum; + + if ([NSApp macOSVersion] < 101000) { + Tcl_AppendResult(interp, + "StatusItem icons not supported on macOS versions lower than 10.10", + NULL); + return TCL_OK; + } + + StatusItemInfo info = (StatusItemInfo)clientData; + TkStatusItem *statusItem = *info; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "create | modify | destroy"); + return TCL_ERROR; + } + + result = Tcl_GetIndexFromObjStruct(interp, objv[1], options, + sizeof(char *), "command", 0, &idx); + + if (result != TCL_OK) { + return TCL_ERROR; + } + switch((optionsEnum)idx) { + case TRAY_CREATE: { + + if (objc < 3 || objc > 6) { + Tcl_WrongNumArgs(interp, 1, objv, "create -image -text -button1 -button3"); + return TCL_ERROR; + } + + if (statusItem == NULL) { + statusItem = [[TkStatusItem alloc] init: interp]; + *info = statusItem; + } else { + Tcl_AppendResult(interp, "Only one system tray icon supported per interpreter", NULL); + return TCL_ERROR; + } + + /* + * Create the icon. + */ + + int width, height; + Tk_Window tkwin = Tk_MainWindow(interp); + TkWindow *winPtr = (TkWindow *)tkwin; + Display *d = winPtr->display; + NSImage *icon; + + tk_image = Tk_GetImage(interp, tkwin, Tcl_GetString(objv[2]), NULL, NULL); + if (tk_image == NULL) { + return TCL_ERROR; + } + + Tk_SizeOfImage(tk_image, &width, &height); + if (width != 0 && height != 0) { + icon = TkMacOSXGetNSImageFromTkImage(d, tk_image, + width, height); + [statusItem setImagewithImage: icon]; + Tk_FreeImage(tk_image); + } + + /* + * Set the text for the tooltip. + */ + + NSString *tooltip = [NSString stringWithUTF8String: Tcl_GetString(objv[3])]; + if (tooltip == nil) { + Tcl_AppendResult(interp, " unable to set tooltip for systray icon", NULL); + return TCL_ERROR; + } + + [statusItem setTextwithString: tooltip]; + + /* + * Set the proc for the callback. + */ + + [statusItem setB1Callback : (objc > 4) ? objv[4] : NULL]; + [statusItem setB3Callback : (objc > 5) ? objv[5] : NULL]; + break; + + } + case TRAY_MODIFY: { + if (objc != 4) { + Tcl_WrongNumArgs(interp, 1, objv, "modify object item"); + return TCL_ERROR; + } + + /* + * Modify the icon. + */ + + result = Tcl_GetIndexFromObjStruct(interp, objv[2], modifyOptions, + sizeof(char *), "option", 0, &idx); + + if (result != TCL_OK) { + return TCL_ERROR; + } + switch ((modifyOptionsEnum)idx) { + case TRAY_IMAGE: { + Tk_Window tkwin = Tk_MainWindow(interp); + TkWindow *winPtr = (TkWindow *)tkwin; + Display *d = winPtr -> display; + NSImage *icon; + int width, height; + + tk_image = Tk_GetImage(interp, tkwin, Tcl_GetString(objv[3]), NULL, NULL); + if (tk_image == NULL) { + Tcl_AppendResult(interp, " unable to obtain image for systray icon", + NULL); + return TCL_ERROR; + } + + Tk_SizeOfImage(tk_image, &width, &height); + if (width != 0 && height != 0) { + icon = TkMacOSXGetNSImageFromTkImage(d, tk_image, + width, height); + [statusItem setImagewithImage: icon]; + } + Tk_FreeImage(tk_image); + break; + } + + /* + * Modify the text for the tooltip. + */ + + case TRAY_TEXT: { + NSString *tooltip = [NSString stringWithUTF8String:Tcl_GetString(objv[3])]; + if (tooltip == nil) { + Tcl_AppendResult(interp, "unable to set tooltip for systray icon", + NULL); + return TCL_ERROR; + } + + [statusItem setTextwithString: tooltip]; + break; + } + + /* + * Modify the proc for the callback. + */ + + case TRAY_B1_CALLBACK: { + [statusItem setB1Callback : objv[3]]; + break; + } + case TRAY_B3_CALLBACK: { + [statusItem setB3Callback : objv[3]]; + break; + } + } + break; + } + + case TRAY_DESTROY: { + /* + * Set all properties to nil, and release statusItem. + */ + [statusItem setImagewithImage: nil]; + [statusItem setTextwithString: nil]; + [statusItem setB1Callback : NULL]; + [statusItem setB3Callback : NULL]; + [statusItem release]; + *info = NULL; + statusItem = NULL; + break; + } + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * SysNotifyObjCmd -- + * + * Create system notification. + * + * Results: + * + * A standard Tcl result. + * + * Side effects: + * + * System notifications are posted. + * + *-------------------------------z--------------------------------------- + */ + +static int SysNotifyObjCmd( + TCL_UNUSED(void *), + Tcl_Interp * interp, + int objc, + Tcl_Obj *const *objv) +{ + if (objc < 3) { + Tcl_WrongNumArgs(interp, 1, objv, "title message"); + return TCL_ERROR; + } + + if ([NSApp macOSVersion] < 101000) { + Tcl_AppendResult(interp, + "Notifications not supported on macOS versions lower than 10.10", + NULL); + return TCL_OK; + } + + /* + * Using NSAppleScript API here allows us to use a single API rather + * than multiple, some deprecated, API's, and also allows notifications + * to work correctly without requiring Wish to be code-signed - an + * undocumented but apparently consistent requirement. And by calling + * NSAppleScript inline rather than shelling to out osascript, + * Wish shows correctly as the calling app rather than Script Editor. + */ + + NSString *title = [NSString stringWithUTF8String: Tcl_GetString(objv[1])]; + NSString *message = [NSString stringWithUTF8String: Tcl_GetString(objv[2])]; + NSMutableString *notify = [NSMutableString new]; + [notify appendString: @"display notification "]; + [notify appendString:@"\""]; + [notify appendString:message]; + [notify appendString:@"\""]; + [notify appendString:@" with title \""]; + [notify appendString:title]; + [notify appendString:@"\""]; + NSAppleScript *scpt = [[[NSAppleScript alloc] initWithSource:notify] autorelease]; + NSDictionary *errorInfo; + NSAppleEventDescriptor *result = [scpt executeAndReturnError:&errorInfo]; + NSString *info = [result stringValue]; + const char* output = [info UTF8String]; + + Tcl_AppendResult(interp, + output, + NULL); + + return TCL_OK; +} + + +/* + *---------------------------------------------------------------------- + * + * MacSystrayInit -- + * + * Initialize this package and create script-level commands. + * This is called from TkpInit for each interpreter. + * + * Results: + * + * A standard Tcl result. + * + * Side effects: + * + * The tk systray and tk sysnotify commands are installed in an + * interpreter + * + *---------------------------------------------------------------------- + */ + +int +MacSystrayInit(Tcl_Interp *interp) +{ + + /* + * Initialize the TkStatusItem for this interpreter. + */ + + StatusItemInfo info = (StatusItemInfo) ckalloc(sizeof(StatusItemInfo)); + *info = 0; + + Tcl_CreateObjCommand(interp, "::tk::systray::_systray", MacSystrayObjCmd, info, + (Tcl_CmdDeleteProc *)MacSystrayDestroy); + Tcl_CreateObjCommand(interp, "::tk::sysnotify::_sysnotify", SysNotifyObjCmd, NULL, NULL); + return TCL_OK; +} + + +/* + * Local Variables: + * mode: objc + * c-basic-offset: 4 + * fill-column: 79 + * coding: utf-8 + * End: + */ Index: macosx/tkMacOSXTest.c ================================================================== --- macosx/tkMacOSXTest.c +++ macosx/tkMacOSXTest.c @@ -2,13 +2,13 @@ * tkMacOSXTest.c -- * * Contains commands for platform specific tests for * the Macintosh platform. * - * Copyright (c) 1996 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen + * Copyright © 1996 Sun Microsystems, Inc. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -374,11 +374,11 @@ windowNumber:0 context:nil characters:chars charactersIgnoringModifiers:unmod isARepeat:NO - keyCode:macKC.v.virtual]; + keyCode:macKC.v.virt]; [NSApp postEvent:keyEvent atStart:NO]; return TCL_OK; } /* * Local Variables: Index: macosx/tkMacOSXWindowEvent.c ================================================================== --- macosx/tkMacOSXWindowEvent.c +++ macosx/tkMacOSXWindowEvent.c @@ -2,14 +2,14 @@ * tkMacOSXWindowEvent.c -- * * This file defines the routines for both creating and handling Window * Manager class events for Tk. * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright (c) 2015 Kevin Walzer/WordTech Communications LLC. - * Copyright (c) 2015 Marc Culler. + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2015 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2015 Marc Culler. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -289,10 +289,20 @@ #undef observe } @end + +/* + * Idle task which forces focus to a particular window. + */ + +static void RefocusGrabWindow(void *data) { + TkWindow *winPtr = (TkWindow *) data; + TkpChangeFocus(winPtr, 1); +} + #pragma mark TKApplication(TKApplicationEvent) @implementation TKApplication(TKApplicationEvent) - (void) applicationActivate: (NSNotification *) notification @@ -306,19 +316,28 @@ /* * When the application is activated with Command-Tab it will create a * zombie window for every Tk window which has been withdrawn. So iterate * through the list of windows and order out any withdrawn window. + * If one of the windows is the grab window for its display we focus + * it. This is done as at idle, in case the app was reactivated by + * clicking a different window. In that case we need to wait until the + * mouse event has been processed before focusing the grab window. */ for (NSWindow *win in [NSApp windows]) { TkWindow *winPtr = TkMacOSXGetTkWindow(win); if (!winPtr || !winPtr->wmInfoPtr) { continue; } if (winPtr->wmInfoPtr->hints.initial_state == WithdrawnState) { [win orderOut:nil]; + } + if (winPtr->dispPtr->grabWinPtr == winPtr) { + Tcl_DoWhenIdle(RefocusGrabWindow, winPtr); + } else { + [[self keyWindow] orderFront: self]; } } } - (void) applicationDeactivate: (NSNotification *) notification @@ -912,16 +931,64 @@ { return (eventPtr->type==ConfigureNotify ? TK_PROCESS_EVENT : TK_DEFER_EVENT); } @implementation TKContentView(TKWindowEvent) + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + /* + * The layer must exist before we set wantsLayer to YES. + */ + + self.layer = [CALayer layer]; + self.wantsLayer = YES; + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay; + self.layer.contentsGravity = self.layer.contentsAreFlipped ? + kCAGravityTopLeft : kCAGravityBottomLeft; + + /* + * Nothing gets drawn at all if the layer does not have a delegate. + * Currently, we do not implement any methods of the delegate, however. + */ + + self.layer.delegate = (id) self; + } + return self; +} + +/* + * We will just use drawRect. + */ + +- (BOOL) wantsUpdateLayer +{ + return NO; +} + +- (void) viewDidChangeBackingProperties +{ + + /* + * Make sure that the layer uses a contentScale that matches the + * backing scale factor of the screen. This avoids blurry text whe + * the view is on a Retina display, as well as incorrect size when + * the view is on a normal display. + */ + + self.layer.contentsScale = self.window.screen.backingScaleFactor; +} - (void) addTkDirtyRect: (NSRect) rect { _tkNeedsDisplay = YES; _tkDirtyRect = NSUnionRect(_tkDirtyRect, rect); [NSApp setNeedsToDraw:YES]; + [self setNeedsDisplay:YES]; + [[self layer] setNeedsDisplay]; } - (void) clearTkDirtyRect { _tkNeedsDisplay = NO; Index: macosx/tkMacOSXWm.c ================================================================== --- macosx/tkMacOSXWm.c +++ macosx/tkMacOSXWm.c @@ -3,15 +3,15 @@ * * This module takes care of the interactions between a Tk-based * application and the window manager. Among other things, it implements * the "wm" command and passes geometry information to the window manager. * - * Copyright (c) 1994-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright (c) 2010 Kevin Walzer/WordTech Communications LLC. - * Copyright (c) 2017-2019 Marc Culler. + * Copyright © 1994-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2010 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2017-2019 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ @@ -240,10 +240,13 @@ static int WmGridCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmGroupCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *const objv[]); +static int WmIconbadgeCmd(Tk_Window tkwin, TkWindow *winPtr, + Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmIconbitmapCmd(Tk_Window tkwin, TkWindow *winPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); static int WmIconifyCmd(Tk_Window tkwin, TkWindow *winPtr, @@ -1189,21 +1192,21 @@ { Tk_Window tkwin = (Tk_Window)clientData; static const char *const optionStrings[] = { "aspect", "attributes", "client", "colormapwindows", "command", "deiconify", "focusmodel", "forget", - "frame", "geometry", "grid", "group", + "frame", "geometry", "grid", "group", "iconbadge", "iconbitmap", "iconify", "iconmask", "iconname", "iconphoto", "iconposition", "iconwindow", "manage", "maxsize", "minsize", "overrideredirect", "positionfrom", "protocol", "resizable", "sizefrom", "stackorder", "state", "title", "transient", "withdraw", NULL }; enum options { WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FORGET, - WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, + WMOPT_FRAME, WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBADGE, WMOPT_ICONBITMAP, WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPHOTO, WMOPT_ICONPOSITION, WMOPT_ICONWINDOW, WMOPT_MANAGE, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, @@ -1277,10 +1280,12 @@ return WmGeometryCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GRID: return WmGridCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_GROUP: return WmGroupCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONBADGE: + return WmIconbadgeCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONBITMAP: return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONIFY: return WmIconifyCmd(tkwin, winPtr, interp, objc, objv); case WMOPT_ICONMASK: @@ -1480,11 +1485,11 @@ } tkMacOSXWmAttrNotifyVal = boolean; } break; case WMATT_TITLEPATH: { - const char *path = Tcl_FSGetNativePath(value); + const char *path = (const char *)Tcl_FSGetNativePath(value); NSString *filename = @""; if (path && *path) { filename = [NSString stringWithUTF8String:path]; } @@ -1634,28 +1639,28 @@ for (attribute = 0; attribute < _WMATT_LAST_ATTRIBUTE; ++attribute) { Tcl_ListObjAppendElement(NULL, result, Tcl_NewStringObj(WmAttributeNames[attribute], -1)); Tcl_ListObjAppendElement(NULL, result, - WmGetAttribute(winPtr, macWindow, attribute)); + WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute)); } Tcl_SetObjResult(interp, result); } else if (objc == 4) { /* wm attributes $win -attribute */ if (Tcl_GetIndexFromObjStruct(interp, objv[3], WmAttributeNames, sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { return TCL_ERROR; } - Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, attribute)); + Tcl_SetObjResult(interp, WmGetAttribute(winPtr, macWindow, (WmAttribute)attribute)); } else if ((objc - 3) % 2 == 0) { /* wm attributes $win -att value... */ int i; for (i = 3; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], WmAttributeNames, sizeof(char *), "attribute", 0, &attribute) != TCL_OK) { return TCL_ERROR; } - if (WmSetAttribute(winPtr, macWindow, interp, attribute, objv[i+1]) + if (WmSetAttribute(winPtr, macWindow, interp, (WmAttribute)attribute, objv[i+1]) != TCL_OK) { return TCL_ERROR; } } } else { @@ -1801,11 +1806,11 @@ } wmPtr->cmapList = cmapList; wmPtr->cmapCount = windowObjc; /* - * On the Macintosh all of this is just an excercise in compatability as + * On the Macintosh all of this is just an excercise in compatibility as * we don't support colormaps. If we did they would be installed here. */ return TCL_OK; } @@ -1940,10 +1945,12 @@ transientPtr->flags &= ~WITHDRAWN_BY_CONTAINER; } } } + [[win contentView] setNeedsDisplay:YES]; + Tcl_DoWhenIdle(TkMacOSXDrawAllViews, NULL); return TCL_OK; } /* *---------------------------------------------------------------------- @@ -2330,10 +2337,78 @@ } wmPtr->hints.window_group = Tk_WindowId(tkwin2); wmPtr->hints.flags |= WindowGroupHint; wmPtr->leaderName = (char *)ckalloc(length + 1); strcpy(wmPtr->leaderName, argv3); + } + return TCL_OK; +} + + /*---------------------------------------------------------------------- + * + * WmIconbadgeCmd -- + * + * This procedure is invoked to process the "wm iconbadge" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconbadgeCmd( + TCL_UNUSED(Tk_Window), /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel to work with */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *const objv[]) /* Argument objects. */ +{ + (void) winPtr; + NSString *label; + + if (objc < 4) { + Tcl_WrongNumArgs(interp, 2, objv,"window badge"); + return TCL_ERROR; + } + + label = [NSString stringWithUTF8String:Tcl_GetString(objv[3])]; + + int number = [label intValue]; + NSDockTile *dockicon = [NSApp dockTile]; + + /* + * First, check that the label is not a decimal. If it is, + * return an error. + */ + + if ([label containsString:@"."]) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use \"%s\" as icon badge", Tcl_GetString(objv[3]))); + return TCL_ERROR; + } + + /* + * Next, check that label is an int, empty string, or exclamation + * point. If so, set the icon badge on the Dock icon. Otherwise, + * return an error. + */ + + NSArray *array = @[@"", @"!"]; + if ([array containsObject: label]) { + [dockicon setBadgeLabel:label]; + } else if (number > 0) { + NSString *str = [@(number) stringValue]; + [dockicon setBadgeLabel:str]; + } else { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "can't use \"%s\" as icon badge", Tcl_GetString(objv[3]))); + return TCL_ERROR; } return TCL_OK; } /* @@ -2866,13 +2941,13 @@ *---------------------------------------------------------------------- */ static int WmManageCmd( - TCL_UNUSED(Tk_Window), /* Main window of the application. */ - TkWindow *winPtr, /* Toplevel or Frame to work with */ - Tcl_Interp *interp, /* Current interpreter. */ + TCL_UNUSED(Tk_Window), /* Main window of the application. */ + TkWindow *winPtr, /* Toplevel or Frame to work with */ + Tcl_Interp *interp, /* Current interpreter. */ TCL_UNUSED(int), /* Number of arguments. */ TCL_UNUSED(Tcl_Obj *const *)) /* Argument objects. */ { Tk_Window frameWin = (Tk_Window)winPtr; WmInfo *wmPtr = winPtr->wmInfoPtr; @@ -2886,10 +2961,22 @@ " frame, labelframe or toplevel", Tk_PathName(frameWin))); Tcl_SetErrorCode(interp, "TK", "WM", "MANAGE", NULL); return TCL_ERROR; } + + /* + * Draw the managed widget at the top left corner of its toplevel. + * See [4a40c6cace]. + */ + + if (macWin) { + winPtr->changes.x -= macWin->xOff; + winPtr->changes.y -= macWin->yOff; + XMoveWindow(winPtr->display, winPtr->window, 0, 0); + } + TkFocusSplit(winPtr); Tk_UnmapWindow(frameWin); if (wmPtr == NULL) { TkWmNewWindow(winPtr); if (winPtr->window == None) { @@ -3722,10 +3809,11 @@ RemoveTransient(winPtr); } else { if (TkGetWindowFromObj(interp, tkwin, objv[3], &container) != TCL_OK) { return TCL_ERROR; } + RemoveTransient(winPtr); containerPtr = (TkWindow*) container; while (!Tk_TopWinHierarchy(containerPtr)) { /* * Ensure that the container window is actually a Tk toplevel. */ @@ -4116,11 +4204,11 @@ static void TopLevelEventProc( ClientData clientData, /* Window for which event occurred. */ XEvent *eventPtr) /* Event that just happened. */ { - TkWindow *winPtr = clientData; + TkWindow *winPtr = (TkWindow *)clientData; winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE; if (eventPtr->type == DestroyNotify) { if (!(winPtr->flags & TK_ALREADY_DEAD)) { /* @@ -4202,11 +4290,11 @@ static void UpdateGeometryInfo( ClientData clientData) /* Pointer to the window's record. */ { - TkWindow *winPtr = clientData; + TkWindow *winPtr = (TkWindow *)clientData; WmInfo *wmPtr = winPtr->wmInfoPtr; int x, y, width, height, min, max; wmPtr->flags &= ~WM_UPDATE_PENDING; @@ -5182,11 +5270,11 @@ topPtr->wmInfoPtr->cmapList = newPtr; topPtr->wmInfoPtr->cmapCount = count+1; /* - * On the Macintosh all of this is just an excercise in compatability as + * On the Macintosh all of this is just an excercise in compatibility as * we don't support colormaps. If we did they would be installed here. */ } /* @@ -5502,16 +5590,19 @@ Tk_Window Tk_MacOSXGetTkWindow( void *w) { Window window = None; - TkDisplay *dispPtr = TkGetDisplayList(); if ([(NSWindow *)w respondsToSelector: @selector (tkWindow)]) { window = [(TKWindow *)w tkWindow]; } - return (window != None ? - Tk_IdToWindow(dispPtr->display, window) : NULL); + if (window) { + TkDisplay *dispPtr = TkGetDisplayList(); + return Tk_IdToWindow(dispPtr->display, window); + } else { + return NULL; + } } /* *---------------------------------------------------------------------- * @@ -5560,12 +5651,12 @@ int TkMacOSXZoomToplevel( void *whichWindow, /* The Macintosh window to zoom. */ short zoomPart) /* Either inZoomIn or inZoomOut */ { - NSWindow *window = whichWindow; - TkWindow *winPtr = TkMacOSXGetTkWindow(window); + NSWindow *window = (NSWindow *)whichWindow; + TkWindow *winPtr = (TkWindow *)TkMacOSXGetTkWindow(window); WmInfo *wmPtr; if (!winPtr || !winPtr->wmInfoPtr) { return false; } @@ -5618,11 +5709,11 @@ "style", "tabbingid", "appearance", "isdark", NULL }; enum SubCmds { TKMWS_STYLE, TKMWS_TABID, TKMWS_APPEARANCE, TKMWS_ISDARK }; - Tk_Window tkwin = clientData; + Tk_Window tkwin = (Tk_Window)clientData; TkWindow *winPtr; int index; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); @@ -5911,11 +6002,18 @@ Tcl_Interp *interp, /* Current interpreter. */ TkWindow *winPtr, /* Window to be manipulated. */ int objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { -#if !(MAC_OS_X_VERSION_MAX_ALLOWED < 101200) +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 + (void) interp; + (void) winPtr; + (void) objc; + (void) objv; + return TCL_OK; +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 Tcl_Obj *result = NULL; NSString *idString; NSWindow *win = TkMacOSXGetNSWindowForDrawable(winPtr->window); if (win) { idString = win.tabbingIdentifier; @@ -5990,10 +6088,17 @@ Tcl_Interp *interp, /* Current interpreter. */ TkWindow *winPtr, /* Window to be manipulated. */ int objc, /* Number of arguments. */ Tcl_Obj * const objv[]) /* Argument objects. */ { +#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1090 + (void) interp; + (void) winPtr; + (void) objc; + (void) objv; + return TCL_OK; +#endif #if MAC_OS_X_VERSION_MAX_ALLOWED > 1090 static const char *const appearanceStrings[] = { "aqua", "darkaqua", "auto", NULL }; enum appearances { @@ -6231,10 +6336,11 @@ atts.override_redirect = True; Tk_ChangeWindowAttributes((Tk_Window)winPtr, CWOverrideRedirect, &atts); ApplyContainerOverrideChanges(winPtr, NULL); } + [window display]; } /* *---------------------------------------------------------------------- * @@ -6269,12 +6375,11 @@ TkMacOSXWinBounds(winPtr, &tkBounds); bounds = NSMakeRect(tkBounds.left, [view bounds].size.height - tkBounds.bottom, tkBounds.right - tkBounds.left, tkBounds.bottom - tkBounds.top); - [view setTkNeedsDisplay:YES]; - [view setTkDirtyRect:bounds]; + [view addTkDirtyRect:bounds]; } } /* @@ -6403,10 +6508,23 @@ return; } macWin = TkMacOSXGetNSWindowForDrawable(winPtr->window); + /* + * Make sure windows are updated before the state change. As an exception, + * do not process idle tasks before withdrawing a window. The purpose of + * this is to support the common paradigm of immediately withdrawing the + * root window. Processing idle tasks before changing the state causes the + * root to briefly flash on the screen, which users of this paradigm find + * annoying. Not processing the events does not guarantee that the window + * will not appear but makes it more likely. + */ + + if (state != WithdrawnState) { + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) {}; + } if (state == WithdrawnState) { Tk_UnmapWindow((Tk_Window)winPtr); } else if (state == IconicState) { /* @@ -6423,12 +6541,13 @@ Tk_MapWindow((Tk_Window)winPtr); [macWin deminiaturize:NSApp]; [macWin orderFront:NSApp]; TkMacOSXZoomToplevel(macWin, state == NormalState ? inZoomIn : inZoomOut); } + /* - * Make sure windows are updated after the state change. + * Make sure windows are updated after the state change too. */ while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)){} } @@ -6677,11 +6796,11 @@ Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); WmStackorderToplevelWrapperMap(parentPtr, parentPtr->display, &table); for (NSWindow *w in backToFront) { hPtr = Tcl_FindHashEntry(&table, (char*) w); if (hPtr != NULL) { - childWinPtr = Tcl_GetHashValue(hPtr); + childWinPtr = (TkWindow *)Tcl_GetHashValue(hPtr); *windowPtr++ = childWinPtr; } } *windowPtr = NULL; Tcl_DeleteHashTable(&table); @@ -6860,11 +6979,11 @@ * allow the window to be resized when it is a split * window. To work around this we make the max size equal * to the screen size. (For 10.11 and up, only) */ - if (@available(macOS 10.11, *)) { + if ([NSApp macOSVersion] >= 101100) { NSSize screenSize = [[macWindow screen] frame].size; [macWindow setMaxFullScreenContentSize:screenSize]; } } } @@ -7002,11 +7121,11 @@ [macWindow setStyleMask:styleMask]; [macWindow setTitle:[NSString stringWithUTF8String:title]]; [macWindow setExcludedFromWindowsMenu:NO]; wmPtr->flags &= ~WM_TOPMOST; } - if (wmPtr->container != None) { + if (wmPtr->container != NULL) { TkWindow *containerWinPtr = (TkWindow *)wmPtr->container; if (containerWinPtr && (containerWinPtr->window != None) && TkMacOSXHostToplevelExists(containerWinPtr)) { NSWindow *containerMacWin = TkMacOSXGetNSWindowForDrawable( Index: macosx/tkMacOSXWm.h ================================================================== --- macosx/tkMacOSXWm.h +++ macosx/tkMacOSXWm.h @@ -1,12 +1,12 @@ /* * tkMacOSXWm.h -- * * Declarations of Macintosh specific window manager structures. * - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2006-2009 Daniel A. Steffen + * Copyright © 2001-2009 Apple Inc. + * Copyright © 2006-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXXCursors.h ================================================================== --- macosx/tkMacOSXXCursors.h +++ macosx/tkMacOSXXCursors.h @@ -3,13 +3,13 @@ * * This file defines a set of Macintosh cursors that * emulate the X cursor set. All of these cursors were * constructed and donated by Grant Neufeld. (gneufeld@ccs.carleton.ca) * - * Copyright (c) 1995-1996 Sun Microsystems, Inc. - * Copyright 2008-2009, Apple Inc. - * Copyright (c) 2008-2009 Daniel A. Steffen + * Copyright © 1995-1996 Sun Microsystems, Inc. + * Copyright © 2008-2009 Apple Inc. + * Copyright © 2008-2009 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/tkMacOSXXStubs.c ================================================================== --- macosx/tkMacOSXXStubs.c +++ macosx/tkMacOSXXStubs.c @@ -4,14 +4,14 @@ * This file contains most of the X calls called by Tk. Many of these * calls are just stubs and either don't make sense on the Macintosh or * their implementation just doesn't do anything. Other calls will * eventually be moved into other files. * - * Copyright (c) 1995-1997 Sun Microsystems, Inc. - * Copyright 2001-2009, Apple Inc. - * Copyright (c) 2005-2009 Daniel A. Steffen - * Copyright 2014 Marc Culler. + * Copyright © 1995-1997 Sun Microsystems, Inc. + * Copyright © 2001-2009, Apple Inc. + * Copyright © 2005-2009 Daniel A. Steffen + * Copyright © 2014 Marc Culler. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ Index: macosx/ttkMacOSXTheme.c ================================================================== --- macosx/ttkMacOSXTheme.c +++ macosx/ttkMacOSXTheme.c @@ -1,16 +1,16 @@ /* * ttkMacOSXTheme.c -- * * Tk theme engine for Mac OSX, using the Appearance Manager API. * - * Copyright (c) 2004 Joe English - * Copyright (c) 2005 Neil Madden - * Copyright (c) 2006-2009 Daniel A. Steffen - * Copyright 2008-2009, Apple Inc. - * Copyright 2009 Kevin Walzer/WordTech Communications LLC. - * Copyright 2019 Marc Culler + * Copyright © 2004 Joe English + * Copyright © 2005 Neil Madden + * Copyright © 2006-2009 Daniel A. Steffen + * Copyright © 2008-2009 Apple Inc. + * Copyright © 2009 Kevin Walzer/WordTech Communications LLC. + * Copyright © 2019 Marc Culler * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * See also: @@ -29,20 +29,22 @@ * window, not to the Tk_Window. BoxToRect() accounts for this. */ #include "tkMacOSXPrivate.h" #include "ttk/ttkTheme.h" -#include /* * Macros for handling drawing contexts. */ -#define BEGIN_DRAWING(d) { \ - TkMacOSXDrawingContext dc; \ - if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) {return;} -#define END_DRAWING \ +#define BEGIN_DRAWING(d) { \ + TkMacOSXDrawingContext dc; \ + if (!TkMacOSXSetupDrawingContext((d), NULL, &dc)) { \ + return; \ + } \ + +#define END_DRAWING \ TkMacOSXRestoreDrawingContext(&dc);} #define HIOrientation kHIThemeOrientationNormal #define NoThemeMetric 0xFFFFFFFF @@ -1349,11 +1351,11 @@ TCL_UNUSED(Ttk_Padding *)) { ThemeButtonParams *params = (ThemeButtonParams *)clientData; if (params->heightMetric != NoThemeMetric) { - ChkErr(GetThemeMetric, params->heightMetric, minHeight); + ChkErr(GetThemeMetric, params->heightMetric, (SInt *) minHeight); /* * The theme height does not include the 1-pixel border around * the button, although it does include the 1-pixel shadow at * the bottom. @@ -1378,11 +1380,11 @@ Tk_Window tkwin, int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - ThemeButtonParams *params = clientData; + ThemeButtonParams *params = (ThemeButtonParams *)clientData; const HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, 0, tkwin); static const CGRect scratchBounds = {{0, 0}, {100, 100}}; CGRect contentBounds, backgroundBounds; int verticalPad; @@ -1424,11 +1426,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - ThemeButtonParams *params = clientData; + ThemeButtonParams *params = (ThemeButtonParams *)clientData; CGRect bounds = BoxToRect(d, b); HIThemeButtonDrawInfo info = computeButtonDrawInfo(params, state, tkwin); bounds = NormalizeButtonBounds(params->heightMetric, bounds); @@ -1768,11 +1770,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - EntryElement *e = elementRecord; + EntryElement *e = (EntryElement *)elementRecord; Ttk_Box inner = Ttk_PadBox(b, Ttk_UniformPadding(3)); CGRect bounds = BoxToRect(d, inner); NSColor *background; Tk_3DBorder backgroundPtr = NULL; static const char *defaultBG = ENTRY_DEFAULT_BACKGROUND; @@ -1870,23 +1872,28 @@ * With no help available from HIToolbox, we have to use hard-wired * constants for the padding. We shift the bounding rectangle downward by * 1 pixel to account for the fact that the button is not centered. */ -static Ttk_Padding ComboboxPadding = {4, 2, 20, 2}; +static Ttk_Padding ComboboxPadding = {4, 4, 20, 4}; +static Ttk_Padding DarkComboboxPadding = {6, 6, 22, 6}; static void ComboboxElementSize( TCL_UNUSED(void *), TCL_UNUSED(void *), - TCL_UNUSED(Tk_Window), + Tk_Window tkwin, int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { *minWidth = 24; *minHeight = 23; - *paddingPtr = ComboboxPadding; + if (TkMacOSXInDarkMode(tkwin)) { + *paddingPtr = DarkComboboxPadding; + } else { + *paddingPtr = ComboboxPadding; + } } static void ComboboxElementDraw( TCL_UNUSED(void *), TCL_UNUSED(void *), @@ -1903,23 +1910,28 @@ .value = Ttk_StateTableLookup(ButtonValueTable, state), .adornment = Ttk_StateTableLookup(ButtonAdornmentTable, state), }; BEGIN_DRAWING(d) - bounds.origin.y += 1; if (TkMacOSXInDarkMode(tkwin)) { - bounds.size.height += 1; + bounds = CGRectInset(bounds, 3, 3); + if (state & TTK_STATE_FOCUS) { + DrawDarkFocusRing(bounds, dc.context); + } DrawDarkButton(bounds, info.kind, state, dc.context); - } else if ([NSApp macOSVersion] > 100800) { - if ((state & TTK_STATE_BACKGROUND) && - !(state & TTK_STATE_DISABLED)) { - NSColor *background = [NSColor textBackgroundColor]; - CGRect innerBounds = CGRectInset(bounds, 1, 2); - SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); - } - } - ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } else { + if ([NSApp macOSVersion] > 100800) { + if ((state & TTK_STATE_BACKGROUND) && + !(state & TTK_STATE_DISABLED)) { + NSColor *background = [NSColor textBackgroundColor]; + CGRect innerBounds = CGRectInset(bounds, 1, 4); + bounds.origin.y += 1; + SolidFillRoundedRectangle(dc.context, innerBounds, 4, background); + } + } + ChkErr(HIThemeDrawButton, &bounds, &info, dc.context, HIOrientation, NULL); + } END_DRAWING } static Ttk_ElementSpec ComboboxElementSpec = { TK_STYLE_VERSION_2, @@ -2131,12 +2143,12 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - TrackElementData *data = clientData; - TrackElement *elem = elementRecord; + TrackElementData *data = (TrackElementData *)clientData; + TrackElement *elem = (TrackElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; double from = 0, to = 100, value = 0, factor; CGRect bounds; TtkGetOrientFromObj(NULL, elem->orientObj, &orientation); @@ -2277,45 +2289,61 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - PbarElement *pbar = elementRecord; + PbarElement *pbar = (PbarElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; - int phase = 0; - double value = 0, maximum = 100, factor; + + /* + * Using 1000 as the maximum should give better than 1 pixel + * resolution for most progress bars. + */ + + int kind, phase = 0, ivalue, imaximum = 1000; CGRect bounds; TtkGetOrientFromObj(NULL, pbar->orientObj, &orientation); - Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value); - Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum); - Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); - factor = RangeToFactor(maximum); + kind = !strcmp("indeterminate", Tcl_GetString(pbar->modeObj)) ? + kThemeIndeterminateBar : kThemeProgressBar; + if (kind == kThemeIndeterminateBar) { + Tcl_GetIntFromObj(NULL, pbar->phaseObj, &phase); + + /* + * On macOS 11 the fraction of an indeterminate progress bar which is + * traversed by the oscillating thumb is value / maximum. The phase + * determines the position of the moving thumb in that range and is + * apparently expected to vary between 0 and 120. On earlier systems + * it is unclear how the phase is used in generating the animation. + */ + + ivalue = imaximum; + } else { + double value, maximum; + Tcl_GetDoubleFromObj(NULL, pbar->valueObj, &value); + Tcl_GetDoubleFromObj(NULL, pbar->maximumObj, &maximum); + ivalue = (value / maximum)*1000; + } /* * HIThemeTrackDrawInfo uses 2-byte alignment; assigning to a separate * bounds variable avoids UBSan (-fsanitize=alignment) complaints. */ bounds = BoxToRect(d, b); HIThemeTrackDrawInfo info = { .version = 0, - .kind = - (!strcmp("indeterminate", - Tcl_GetString(pbar->modeObj)) && value) ? - kThemeIndeterminateBar : kThemeProgressBar, + .kind = kind, .bounds = bounds, .min = 0, - .max = maximum * factor, - .value = value * factor, + .max = imaximum, + .value = ivalue, .attributes = kThemeTrackShowThumb | - (orientation == TTK_ORIENT_HORIZONTAL ? - kThemeTrackHorizontal : 0), + (orientation == TTK_ORIENT_HORIZONTAL ? kThemeTrackHorizontal : 0), .enableState = Ttk_StateTableLookup(ThemeTrackEnableTable, state), - .trackInfo.progress.phase = phase, + .trackInfo.progress.phase = phase }; - BEGIN_DRAWING(d) if (TkMacOSXInDarkMode(tkwin)) { bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *trackColor = [NSColor colorWithColorSpace: deviceRGB @@ -2360,11 +2388,11 @@ TCL_UNUSED(Tk_Window), int *minWidth, int *minHeight, Ttk_Padding *paddingPtr) { - ScrollbarElement *scrollbar = elementRecord; + ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; SInt32 thickness = 15; TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation); ChkErr(GetThemeMetric, kThemeMetricScrollBarWidth, &thickness); @@ -2401,11 +2429,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, TCL_UNUSED(Ttk_State)) { - ScrollbarElement *scrollbar = elementRecord; + ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; CGRect bounds = BoxToRect(d, b); NSColorSpace *deviceRGB = [NSColorSpace deviceRGBColorSpace]; NSColor *troughColor; CGFloat *rgba = TkMacOSXInDarkMode(tkwin) ? darkTrough : lightTrough; @@ -2443,11 +2471,11 @@ TCL_UNUSED(Tk_Window), int *minWidth, int *minHeight, TCL_UNUSED(Ttk_Padding *)) { - ScrollbarElement *scrollbar = elementRecord; + ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation); if (orientation == TTK_ORIENT_VERTICAL) { *minHeight = 18; @@ -2464,11 +2492,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - ScrollbarElement *scrollbar = elementRecord; + ScrollbarElement *scrollbar = (ScrollbarElement *)elementRecord; Ttk_Orient orientation = TTK_ORIENT_HORIZONTAL; TtkGetOrientFromObj(NULL, scrollbar->orientObj, &orientation); /* @@ -2858,11 +2886,11 @@ /*---------------------------------------------------------------------- * +++ Field elements -- * * Used for the Treeview widget. This is like the BackgroundElement - * except that the fieldbackground color is configureable. + * except that the fieldbackground color is configurable. */ typedef struct { Tcl_Obj *backgroundObj; } FieldElement; @@ -2879,11 +2907,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, TCL_UNUSED(Ttk_State)) { - FieldElement *e = elementRecord; + FieldElement *e = (FieldElement *)elementRecord; Tk_3DBorder backgroundPtr = Tk_Get3DBorderFromObj(tkwin, e->backgroundObj); XFillRectangle(Tk_Display(tkwin), d, Tk_3DBorderGC(tkwin, backgroundPtr, TK_3D_FLAT_GC), @@ -2971,11 +2999,11 @@ Tk_Window tkwin, Drawable d, Ttk_Box b, Ttk_State state) { - ThemeButtonParams *params = clientData; + ThemeButtonParams *params = (ThemeButtonParams *)clientData; CGRect bounds = BoxToRect(d, b); const HIThemeButtonDrawInfo info = { .version = 0, .state = Ttk_StateTableLookup(ThemeStateTable, state), .kind = params->kind, Index: tests/all.tcl ================================================================== --- tests/all.tcl +++ tests/all.tcl @@ -2,16 +2,16 @@ # # This file contains a top-level script to run all of the Tk # tests. Execute it by invoking "source all.tcl" when running tktest # in this directory. # -# Copyright © 1998-1999 by Scriptics Corporation. +# Copyright © 1998-1999 Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. -package require Tk ;# This is the Tk test suite; fail early if no Tk! +package require tk ;# This is the Tk test suite; fail early if no Tk! package require tcltest 2.2 tcltest::configure {*}$argv tcltest::configure -testdir [file normalize [file dirname [info script]]] tcltest::configure -loadfile \ [file join [tcltest::testsDirectory] constraints.tcl] Index: tests/bell.test ================================================================== --- tests/bell.test +++ tests/bell.test @@ -1,10 +1,10 @@ # This file is a Tcl script to test out Tk's "bell" command. # It is organized in the standard fashion for Tcl tests. # # Copyright © 1994 The Regents of the University of California. -# Copyright © 1998-2000 by Scriptics Corporation. +# Copyright © 1998-2000 Scriptics Corporation. # All rights reserved. package require tcltest 2.2 namespace import ::tcltest::* eval tcltest::configure $argv Index: tests/bgerror.test ================================================================== --- tests/bgerror.test +++ tests/bgerror.test @@ -1,10 +1,10 @@ # This file is a Tcl script to test the bgerror command. # It is organized in the standard fashion for Tcl tests. # # Copyright © 1997 Sun Microsystems, Inc. -# Copyright © 1998-1999 by Scriptics Corporation. +# Copyright © 1998-1999 Scriptics Corporation. # All rights reserved. package require tcltest 2.2 namespace import ::tcltest::* eval tcltest::configure $argv Index: tests/bind.test ================================================================== --- tests/bind.test +++ tests/bind.test @@ -2,20 +2,22 @@ # commands plus the procedures in tkBind.c. It is organized in the # standard fashion for Tcl tests. # # Copyright © 1994 The Regents of the University of California. # Copyright © 1994-1995 Sun Microsystems, Inc. -# Copyright © 1998-1999 by Scriptics Corporation. +# Copyright © 1998-1999 Scriptics Corporation. # All rights reserved. package require tcltest 2.2 namespace import ::tcltest::* eval tcltest::configure $argv tcltest::loadTestedCommands tk useinputmethods 0 testConstraint nodeprecated [expr {"nodeprecated" ni [tk::pkgconfig list]}] +testConstraint needsTcl87 [package vsatisfies [package provide Tcl] 8.7-] +testConstraint failsOnWindows [expr {![info exists ::env(CI)] || [tk windowingsystem] ne "win32"}] toplevel .t -width 100 -height 50 wm geom .t +0+0 update idletasks @@ -41,11 +43,11 @@ # otherwise some spurious events may pollute the tests toplevel .top wm geometry .top 50x50-50-50 update event generate .top -warp 1 -update +controlPointerWarpTiming destroy .top test bind-1.1 {bind command} -body { bind } -returnCodes error -result {wrong # args: should be "bind window ?pattern? ?command?"} @@ -385,17 +387,17 @@ destroy .t.c } -result {Test} test bind-11.1 {Tk_GetAllBindings procedure} -body { frame .t.f - foreach i "! a \\\{ ~ <> " { + foreach i "! a \\\{ ~ <> <Â>" { bind .t.f $i Test } lsort [bind .t.f] } -cleanup { destroy .t.f -} -result {! <> a \{ ~} +} -result "! <> a \\\{ ~" test bind-11.2 {Tk_GetAllBindings procedure} -body { frame .t.f foreach i " " { bind .t.f $i Test } @@ -437,21 +439,21 @@ bind all {lappend x "%W %K all Key"} bind Test : {lappend x "%W %K Test :"} bind all _ {lappend x "%W %K all _"} bind .t.f : {lappend x "%W %K .t.f :"} - event generate .t.f - event generate .t.f - event generate .t.f + event generate .t.f <:> + event generate .t.f <+> + event generate .t.f <_> return $x } -cleanup { destroy .t.f bind all {} bind Test {} bind all _ {} bind Test : {} -} -result {{.t.f colon .t.f :} {.t.f colon Test :} {.t.f colon all Key} {.t.f plus Test Key} {.t.f plus all Key} {.t.f underscore Test Key} {.t.f underscore all _}} +} -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 _}} test bind-13.2 {Tk_BindEvent procedure} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f focus -force .t.f @@ -460,17 +462,17 @@ } -body { bind Test {lappend x "%W %K Test press any"; break} bind all {continue; lappend x "%W %K all press any"} bind .t.f : {lappend x "%W %K .t.f pressed colon"} - event generate .t.f + event generate .t.f <:> return $x } -cleanup { destroy .t.f bind all {} bind Test {} -} -result {{.t.f colon .t.f pressed colon} {.t.f colon Test press any}} +} -result {{.t.f : .t.f pressed colon} {.t.f : Test press any}} test bind-13.3 {Tk_BindEvent procedure} -setup { proc bgerror args {} frame .t.f -class Test -width 150 -height 100 pack .t.f @@ -478,25 +480,25 @@ update set x {} } -body { bind Test {lappend x "%W %K Test press any"; error Test} bind .t.f : {lappend x "%W %K .t.f pressed colon"} - event generate .t.f + event generate .t.f <:> update list $x $errorInfo } -cleanup { destroy .t.f bind Test {} rename bgerror {} -} -result {{{.t.f colon .t.f pressed colon} {.t.f colon Test press any}} {Test +} -result {{{.t.f : .t.f pressed colon} {.t.f : Test press any}} {Test while executing "error Test" (command bound to event)}} test bind-13.4 {Tk_BindEvent procedure} -setup { proc foo {} { set x 44 - event generate .t.f + event generate .t.f <:> } frame .t.f -class Test -width 150 -height 100 pack .t.f focus -force .t.f update @@ -507,11 +509,11 @@ foo return $x } -cleanup { destroy .t.f bind Test : {} -} -result {{.t.f colon .t.f} {.t.f colon Test}} +} -result {{.t.f : .t.f} {.t.f : Test}} test bind-13.5 {Tk_BindEvent procedure} -body { bind all {lappend x "%W destroyed"} set x {} frame .t.g -gorp foo @@ -535,11 +537,11 @@ set x {} } -body { bind .t.f : {lappend x "%W (.t.f binding)"} bind Test : {lappend x "%W (Test binding)"} bind all : {bind .t.f : {}; lappend x "%W (all binding)"} - event generate .t.f + event generate .t.f <:> return $x } -cleanup { bind Test : {} bind all : {} destroy .t.f @@ -552,11 +554,11 @@ set x {} } -body { bind .t.f : {lappend x "%W (.t.f binding)"} bind Test : {lappend x "%W (Test binding)"} bind all : {destroy .t.f; lappend x "%W (all binding)"} - event generate .t.f + event generate .t.f <:> return $x } -cleanup { bind Test : {} bind all : {} destroy .t.f @@ -634,16 +636,16 @@ update set x {} } -body { bind .t.f "lappend x Key%K" bind .t.f "lappend x Release%K" - event generate .t.f -keysym colon - event generate .t.f -keysym colon + event generate .t.f -keysym : + event generate .t.f -keysym : return $x } -cleanup { destroy .t.f -} -result {Keycolon Releasecolon} +} -result {Key: Release:} test bind-13.14 {Tk_BindEvent procedure: invalid key detail} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f focus -force .t.f update @@ -1043,10 +1045,11 @@ } -result {b1 {invalid command name "blap"}} test bind-15.1 {MatchPatterns procedure, ignoring type mismatches} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f + update idletasks focus -force .t.f update } -body { bind .t.f 12 {set x 1} set x 0 @@ -1059,10 +1062,11 @@ destroy .t.f } -result 1 test bind-15.2 {MatchPatterns procedure, ignoring type mismatches} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f + update idletasks focus -force .t.f update } -body { bind .t.f 12 {set x 1} set x 0 @@ -1470,10 +1474,11 @@ event delete <> } -result {V2102 V2103 V2105 Shift-Button-1} test bind-15.27 {MatchPatterns procedure, conflict resolution} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f + update idletasks focus -force .t.f update } -body { bind .t.f {set x 0} bind .t.f 1 {set x 1} @@ -1484,10 +1489,11 @@ destroy .t.f } -result 1 test bind-15.28 {MatchPatterns procedure, conflict resolution} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f + update idletasks focus -force .t.f update } -body { bind .t.f {set x 0} bind .t.f 1 {set x 1} @@ -1498,10 +1504,11 @@ destroy .t.f } -result 0 test bind-15.29 {MatchPatterns procedure, conflict resolution} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f + update idletasks focus -force .t.f update } -body { bind .t.f {lappend x 0} bind .t.f 1 {lappend x 1} @@ -2049,11 +2056,11 @@ event generate .t.f event generate .t.f set x } -cleanup { destroy .t.f -} -result {a A { } {\r} {{}} {{}} { } {\$} \\\{ {{}} {{}} \xE9} +} -result {a A { } {\r} {{}} {{}} { } {\$} \\\{ {{}} {{}} é} test bind-16.36 {ExpandPercents procedure} -setup { frame .t.f -class Test -width 150 -height 100 pack .t.f focus -force .t.f update @@ -2221,10 +2228,23 @@ destroy .t.e bind Entry $savedBind(Entry) bind all $savedBind(All) unset savedBind } -result {0 1 2} +test bind-16.47 {ExpandPercents procedure} -constraints {aquaOrWin32 needsTcl87 failsOnWindows} -setup { + frame .t.f -class Test -width 150 -height 100 + pack .t.f + focus -force .t.f + update +} -body { + bind .t.f {set x "%K"} + set x none + event generate .t.f -keysym € + set x +} -cleanup { + destroy .t.f +} -result € test bind-17.1 {event command} -body { event } -returnCodes error -result {wrong # args: should be "event option ?arg?"} test bind-17.2 {event command} -body { @@ -2237,11 +2257,11 @@ event delete <> event add <> event info <> } -cleanup { event delete <> -} -result {} +} -result test bind-17.5 {event command: add 2} -body { event delete <> event add <> lsort [event info <>] } -cleanup { @@ -2350,19 +2370,19 @@ event delete <> event add <> event info <> } -cleanup { event delete <> -} -result {} +} -result test bind-18.4 {CreateVirtualEvent procedure: duplicate physical} -body { event delete <> event add <> event add <> event info <> } -cleanup { event delete <> -} -result {} +} -result test bind-18.5 {CreateVirtualEvent procedure: existing physical} -body { foreach p [event info] {event delete $p} event add <> event add <> list [lsort [event info]] [event info <>] [event info <>] @@ -2407,11 +2427,11 @@ event delete <> } -body { event add <> event delete <> event info <> -} -result {} +} -result test bind-19.5 {DeleteVirtualEvent procedure: delete 1, badly formed} -body { event add <> event delete <> } -cleanup { event delete <> @@ -2689,11 +2709,11 @@ } -body { event add <> event info <> } -cleanup { event delete <> -} -result {} +} -result test bind-20.4 {GetVirtualEvent procedure: owns many} -setup { event delete <> } -body { event add <> spack event info <> @@ -2710,11 +2730,11 @@ foreach p [event info] {event delete $p} event add <> event info } -cleanup { event delete <> -} -result {<>} +} -result <> test bind-21.3 {GetAllVirtualEvents procedure: many events} -body { foreach p [event info] {event delete $p} event add <> event add <> event add <> @@ -5087,11 +5107,11 @@ } -result test test bind-25.2 {ParseEventDescription procedure: misinterpreted modifier} -setup { button .b } -body { bind .b a - bind .b b + bind .b b lsort [bind .b] } -cleanup { destroy .b } -result { } test bind-25.3 {ParseEventDescription procedure} -setup { @@ -5107,11 +5127,11 @@ } -body { bind .t.f <> {puts hi} bind .t.f } -cleanup { destroy .t.f -} -result {<>} +} -result <> # Assorted error cases in event sequence parsing test bind-25.5 {ParseEventDescription procedure error cases} -body { bind .t \x7 {puts hi} } -returnCodes error -result {bad ASCII character 0x7} @@ -5191,11 +5211,11 @@ } -result test bind-25.22 {modifier names} -setup { frame .t.f -class Test -width 150 -height 100 } -body { - bind .t.f foo + bind .t.f foo bind .t.f } -cleanup { destroy .t.f } -result @@ -5536,24 +5556,10 @@ list $x [bind .t.f] } -cleanup { destroy .t.f } -result {{event Button}